"Java Black Book Basics, Tenth Edition" Chapter 17 [Exercise]

Java Language Programming Exercises Chapter 17

17.2 Chapter Exercises

17.1 What is a text file and what is a binary file? Can a text editor be used to view text or binary files?

Text files are files made up of characters, and binary files are files made up of 0s and 1s

Text editors can only access text files

17.2 How to read and write text data in Java? What is a stream?

Scanner class for reading and PrintWriter class for writing

A stream is an object, an object responsible for writing data is called an output stream, and an object responsible for reading data is called an input stream

17.3 Chapter Exercises

17.3 What is the difference between text I/O and binary I/O?

Text I/O requires encoding/decoding to binary, binary I/O does not

17.4 In Java, how are characters represented in memory and how are they represented in text files?

Characters are represented in Unicode in Java memory, and text files are represented using specific encoding rules, such as ASCII

17.5 If you write the string "ABC" in an ASCII text file, what value is stored in the file?

0x41 0x42 0x43

17.6 If you write the string "100" in an ASCII text file, what value is stored in the file? If you write a byte type value of 100 using binary I/O, what value is stored in the file?

0x31 0x30 0x30

0x64

17.7 In a Java program, what is the encoding scheme used to represent a character? What is the encoding scheme for text files in Windows by default?

The Java encoding scheme is Unicode

ASCII

17.4 Chapter Exercises

17.8 In a Java I/O program, why do I have to declare IOException thrown in the method or handle the exception in the try-catch block?

Almost all methods in the binary I/O class throw a must-check exception IOException, and calling these methods requires mandatory declaration or throwing

17.9 Why is it always required to close the stream? How to close the stream?

Ensure that all data can be safely written and release resources at the same time

Use the close method or try-catch-resource

17.10 The read() method of InputStream reads bytes, why does the read() method return an int value instead of bytes? Find out the abstract methods in InputStream and OutputStream

Bytes are returned as an integer from 0-255

Only read() in InputStream is an abstract method

Only write(int) in OutputStream is an abstract method

17.11 Do the FilelnputStream and FileOutputStream classes introduce new methods relative to the InputStream/OutputStream they inherit from? How to create FilelnputStream and FileOutputStream objects?

No new methods were introduced

new FileInputStream()

new FileOutputStream()

17.12 What happens if you try to create an input stream for a file that doesn't exist? What happens if you try to create an output stream for a file that already exists? Can data be appended to an existing file?

An exception FileNotFoundException will occur

The file will be cleared and rewritten

Can

17.13 How to use java.io.PrintWriter to append data to an existing text file?

new Formatter(new FileOutputStream("temp.txt", true));

17.14 If a file contains an unspecified number of double values, use the writeDouble method of DataOutputStream to write these values ​​to the file. How can I write a program to read all these values? How can I detect if the end of this file has been reached?

Use the readDouble() method

Detect reaching end by catching and handling EOFException

17.15 After using the writeByte(91) method on FileOutputStream, what is written to the file?

91

17.16 How to judge whether the end of the file has been reached in the input stream (FilelnputStream and DatalnputStream)?

The read() method returns -1

17.17 What is wrong with the following code?

import java.io.*;

public class Test {
    
    
  public static void main(String[] args) {
    
    
    try (
      FileInputStream fis = new FileInputStream("test.dat"); ) {
    
    
    }
    catch (IOException ex) {
    
    
      ex.printStackTrace();
    }
    catch (FileNotFoundException ex) {
    
    
      ex.printStackTrace();
    }
  }
}

IOException is the parent class of FileNotFoundException, if you write the parent class first, you will never be able to catch the subclass

17.18 Assuming the program is run on Windows using the default ASCII encoding scheme, how many bytes are there in the file t.txt after the program ends? Give the content of each byte.

public class Test {
    
    
  public static void main(String[] args) 
      throws java.io.IOException {
    
    
    try (java.io.PrintWriter output = 
        new java.io.PrintWriter("t.txt"); ) {
    
    
      output.printf("%s", "1234");
      output.printf("%s", "5678");
      output.close();
    }
  }
}

An integer occupies 4 bytes, so the two integers in the question occupy 8 bytes, where the number 1 is represented as 31 in ASCII encoding

31 32 33 34

35 36 37 38

17.19 How many bytes will there be in the file t.dat after the following program is executed? Give the content of each byte.

import java.io.*;

public class Test {
    
    
  public static void main(String[] args) throws IOException {
    
    
    try (DataOutputStream output = new DataOutputStream(
        new FileOutputStream("t.dat")); ) {
    
    
      output.writeInt(1234);
      output.writeInt(5678);
      output.close();
    }
  }
}

An integer occupies 4 bytes, so the two integers in the question occupy 8 bytes

00 00 04 D2

00 00 16 2E

17.20 For the following statements on the output of the DataOutputStream object, how many bytes are sent to the output?

output.writeChar('A');
output.writeChars("BC");
output.writeUTF("DEF");

2, 4, 5 respectively

17.21 What are the benefits of using buffered streams? Is the following statement correct?

BufferedInputStream input1 = new BufferedInputStream(new FileInputStream("t.dat"));

    	DataInputStream input2 = new DataInputStream(new BufferedInputStream(new FileInputStream("t.dat")));

    	DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("t.dat")));

yes

17.5 Chapter Exercises

17.22 How does a program check if a file already exists?

exists() method

17.23 How does the program detect whether it has reached the end of the file when reading data?

The read() method will return -1

17.24 How does a program count the number of bytes read from a file?

numberOfBytesCopied will be +1 each time a byte is read

17.6 Chapter Exercises

17.25 What type of objects can be stored using ObjectOutputStream? What method can write people object? What method can read the object? What is the return type of methods that read objects from ObjectlnputStream?

any serializable object

writeObject

readObject

Object type

17.26 If two objects of the same type are serialized, do they occupy the same space? If not, give an example.

different

For example, if two ArrayLIsts have different elements, they will occupy different spaces.

17.27 Can any instance of java.io.Serializable be successfully serialized? Are static variables of objects serializable? How to mark an instance variable to avoid serialization?

no

Can't

marked as transient

17.28 Can I write an array to ObjectOutputStream?

Can

17.29 In any case, can DatalnputStream and DataOutputStream be replaced by ObjectlnputStream and ObjectOutputStream?

Yes

17.30 What happens when you run the following code?

import java.io.*;
public class Test {
    
    
  public static void main(String[] args) throws IOException {
    
    
    try ( ObjectOutputStream output = 
        new ObjectOutputStream(new FileOutputStream("object.dat")); ) {
    
    
      output.writeObject(new A());
    }
  }
}

class A implements Serializable {
    
    
  B b = new B();
}

class B {
    
     
}

NotSerializableException exception

17.7 Chapter Exercises

17.31 Can RandomAccessFile stream read and write data files created by DataOutputStream? Can the Random-AccessFile stream read and write objects?

Can

Can't

17.32 Create a RandomAccessFile stream for the file address.dat to update the student information in the file. Create a DataOutputStream for the file address.dat. Explain the difference between these two statements.

RandomAccessFile raf = new RandomAccessFile("address.dat", "rw");
DataOutputStream outfile = new DataOutputStream(
  new FileWriter("address.dat"));

17.33 What happens when you try to compile and run the following code if the file test.dat does not exist?

import java.io.*;
public class Test {
    
     
  public static void main(String[] args) {
    
    
    try ( RandomAccessFile raf =
        new RandomAccessFile("test.dat", "r"); ) {
    
    
      int i = raf.readInt();
    }
    catch (IOException ex) {
    
    
      System.out.println("IO exception");
    }
  }
}

will cause a runtime exception

programming exercises

*17.1 (create a text file)

Write a program that, if the file Exercise17_01.txt does not exist, creates a file named Exercise17_01.txt. Append new data to this file. Write 100 randomly generated integers to this file using text I/O. Integers in the file are separated by spaces.

import java.io.*;

public class Test {
    
    
  public static void main(String[] args) throws java.io.IOException {
    
    
	  // true可以保存已有内容,追加新数据
	  FileOutputStream output = new FileOutputStream("Exercise17_01.txt", true);
	  int randomInt;
	  for (int i = 0; i < 100; i++) {
    
    
		  // 0-9的ASCII范围是48-57,空格的ASCII表示是32
		  randomInt = (int)(Math.random() * 10 + 48);
		  output.write(randomInt);
		  output.write(32);
	  }
	  output.close();
  }
}

Output result:

4 6 3 6 9 4 4 1 4 8 8 5 6 1 7 9 1 2 6 5 6 9 2 6 3 6 5 1 9 0 8 2 6 0 2 4 4 9 0 5 7 5 4 1 3 4 9 7 3 9 8 3 1 4 5 1 7 9 0 0 2 8 2 5 9 4 3 7 4 8 1 7 6 8 5 0 1 1 6 3 9 7 6 8 7 4 0 7 7 4 2 4 1 0 6 9 9 1 7 9 
*17.2 (creating binary data files)

Write a program that, if the file Exercise17_02.dat does not exist, creates a file named Exercise17_02.dat. Append new data to this file. Write 100 randomly generated integers to this file using binary I/O.

import java.io.*;

public class Test {
    
    
  public static void main(String[] args) throws java.io.IOException {
    
    
	  // true可以保存已有内容,追加新数据
	  FileOutputStream output = new FileOutputStream("Exercise17_02.dat", true);
	  int randomInt;
	  for (int i = 0; i < 100; i++) {
    
    
		  // 0-9的ASCII范围是48-57
		  randomInt = (int)(Math.random() * 10 + 48);
		  output.write(randomInt);
	  }
	  output.close();
  }
}

Output result:

Exercise17_0.dat
*17.3 (sum all integers in binary data file)

Assuming that a binary data file named Exercise17_03.dat has been created using the writelnt(int) method in DataOutputStream, and the file contains an indeterminate number of integers, write a program to calculate the sum of these integers.

import java.io.*;
import java.util.ArrayList;

public class Test {
    
    
  public static void main(String[] args) throws IOException {
    
    
	  // 全局变量,list用来储存文件中的所有数字,sum用来储存这些数字的和
	  ArrayList<Integer> list = new ArrayList<>();
	  double sum = 0;
	  
	  // 随机写入一些数据
	  try (DataOutputStream output = new DataOutputStream(new FileOutputStream("Exercise17_03.txt"))) {
    
    
		  output.writeInt(50);
		  output.writeInt(32);
		  output.writeInt(88);
	  }
	  
	  // 读取数据,每读取一个数据,就加入到list中,读取完成就捕获异常
	  try (DataInputStream input = new DataInputStream(new FileInputStream("Exercise17_03.txt"))) {
    
    
		  while (true)
			  list.add(input.readInt());
	  } catch (EOFException e) {
    
    
		  System.out.println("End of File");
	  }
	  
	  // 把读取的数据提取出来加和,算平均值
	  for (int i = 0; i < list.size(); i++)
			sum = sum + list.get(i);
	  System.out.printf("The average is %.2f", sum / list.size());
  }
}

Output result:

End of File
The average is 56.67
*17.4 (convert text files to UTF format)

Write a program that reads multiple lines of characters from a text file at a time, and writes these lines of characters into a binary file in UTF-8 string format. Displays the size of text and binary files. Run this program with the following command:

import java.io.*;
import java.util.ArrayList;

public class Test {
    
    
  public static void main(String[] args) throws java.io.IOException {
    
    
	  // 全局变量list用来储存每一个UTF的值
	  ArrayList<String> list = new ArrayList<>();
	  // 两个文件的命令行参数
	  File tempFile = new File(args[0]);
	  File finalFile = new File(args[1]);
	  
	  // 先写入文件
	  try (DataOutputStream output = new DataOutputStream(new FileOutputStream(tempFile))) {
    
    
		  output.writeUTF("Hello, World1!\n");
		  output.writeUTF("Hello, World2!\n");
		  output.writeUTF("Hello, World3!\n");
		  output.writeUTF("Hello, World4!\n");
		  output.writeUTF("Hello, World5!");
	  }
	  
	  // 读取写入的文件
	  try (DataInputStream input = new DataInputStream(new FileInputStream(tempFile))) {
    
    
		  while (true)
			  list.add(input.readUTF());
	  } catch (EOFException e) {
    
    
		  System.out.println("End of File");
	  }
	  
	  // 把读取的内容写入到新的文件
	  try (DataOutputStream output = new DataOutputStream(new FileOutputStream(finalFile))) {
    
    
		  for (int i = 0; i < list.size(); i++) {
    
    
			  output.writeUTF(list.get(i));
		  }
	  }
	  
	  // 打印两个文件大小
	  System.out.println("The original file size is " + tempFile.length() + " bytes");
	  System.out.println("The final file size is " + finalFile.length() + " bytes");
  }
}

Output result:

(base) kevinwang@KevindeMacBook-Pro ~ % java /Users/kevinwang/Eclipse/test/src/Test.java /Users/kevinwang/Eclipse/test/temp.txt /Users/kevinwang/Eclipse/test/final.dat
End of File
The original file size is 84 bytes
The final file size is 84 bytes
*17.5 (store objects and arrays in files)

Write a program to store an array of 5 int values ​​1, 2, 3, 4, 5, a Date object representing the current time, and a double value 5.5 in a file named Exercise17_05.dat

import java.util.Date;
import java.io.*;

public class Test {
    
    
	public static void main(String[] args) {
    
    
		// 初始化3个要求写入的变量
		int[] numbers = {
    
    1, 2, 3, 4, 5};
		Date date = new Date();
		Double doubleNum = 5.5;
		
		// 写入这3个变量
		try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("Exercise17_05.dat"))) {
    
    
			output.writeObject(numbers);
			output.writeObject(date);
			output.writeObject(doubleNum);
		} catch (IOException e) {
    
    
			System.out.println("IOException");
		}
		
		// 读取并打印这3个变量
		try (ObjectInputStream input = new ObjectInputStream(new FileInputStream("Exercise17_05.dat"))) {
    
    
			int[] newNumbers = (int[])input.readObject();
			Date newDate = (Date)input.readObject();
			Double newDoubleNum = (Double)input.readObject();
			
			for (int i = 0; i < newNumbers.length; i++) {
    
    
				System.out.print(newNumbers[i] + " ");
			}
			System.out.println();
			System.out.println(newDate);
			System.out.println(newDoubleNum);
		} catch (IOException e) {
    
    
			System.out.println("IOException");
		} catch (ClassNotFoundException e) {
    
    
			System.out.println("ClassNotFoundException");
		}
 	}
}

Output result:

1 2 3 4 5 
Sat Jun 17 10:08:45 BST 2023
5.5
*17.6 (store Loan object)

The class Loan in the program list 10-2 does not implement Serializable, so rewrite the class Loan to implement Serializable. Write a program to create 5 Loan objects and store them in a file named Excrcise17_06.dat

Test.java

import java.io.*;

public class Test {
    
    
	public static void main(String[] args) {
    
    
		// 初始化5个Loan对象
		Loan loan1 = new Loan(3.5, 5, 10000);
		Loan loan2 = new Loan(4, 5, 20000);
		Loan loan3 = new Loan(4.5, 5, 30000);
		Loan loan4 = new Loan(5, 5, 40000);
		Loan loan5 = new Loan(5.5, 5, 50000);
		
		// 写入这5个对象
		try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("Exercise17_06.dat"))) {
    
    
			output.writeObject(loan1);
			output.writeObject(loan2);
			output.writeObject(loan3);
			output.writeObject(loan4);
			output.writeObject(loan5);
		} catch (IOException e) {
    
    
			System.out.println("IOException");
		}
		
		// 读取并打印这5个对象
		try (ObjectInputStream input = new ObjectInputStream(new FileInputStream("Exercise17_06.dat"))) {
    
    
			Loan newLoan1 = (Loan)input.readObject();
			Loan newLoan2 = (Loan)input.readObject();
			Loan newLoan3 = (Loan)input.readObject();
			Loan newLoan4 = (Loan)input.readObject();
			Loan newLoan5 = (Loan)input.readObject();
			
			System.out.println(newLoan1);
			System.out.println(newLoan2);
			System.out.println(newLoan3);
			System.out.println(newLoan4);
			System.out.println(newLoan5);
		} catch (IOException e) {
    
    
			System.out.println("IOException");
		} catch (ClassNotFoundException e) {
    
    
			System.out.println("ClassNotFoundException");
		}
 	}
}

Loan.java

public class Loan implements java.io.Serializable{
    
    
  private double annualInterestRate;
  private int numberOfYears;
  private double loanAmount;
  private java.util.Date loanDate;

  /** Default constructor */
  public Loan() {
    
    
    this(2.5, 1, 1000);
  }

  /** Construct a loan with specified annual interest rate,
      number of years, and loan amount
    */
  public Loan(double annualInterestRate, int numberOfYears,
      double loanAmount) {
    
    
    this.annualInterestRate = annualInterestRate;
    this.numberOfYears = numberOfYears;
    this.loanAmount = loanAmount;
    loanDate = new java.util.Date();
  }

  /** Return annualInterestRate */
  public double getAnnualInterestRate() {
    
    
    return annualInterestRate;
  }

  /** Set a new annualInterestRate */
  public void setAnnualInterestRate(double annualInterestRate) {
    
    
    this.annualInterestRate = annualInterestRate;
  }

  /** Return numberOfYears */
  public int getNumberOfYears() {
    
    
    return numberOfYears;
  }

  /** Set a new numberOfYears */
  public void setNumberOfYears(int numberOfYears) {
    
    
    this.numberOfYears = numberOfYears;
  }

  /** Return loanAmount */
  public double getLoanAmount() {
    
    
    return loanAmount;
  }

  /** Set a newloanAmount */
  public void setLoanAmount(double loanAmount) {
    
    
    this.loanAmount = loanAmount;
  }

  /** Find monthly payment */
  public double getMonthlyPayment() {
    
    
    double monthlyInterestRate = annualInterestRate / 1200;
    double monthlyPayment = loanAmount * monthlyInterestRate / (1 -
      (1 / Math.pow(1 + monthlyInterestRate, numberOfYears * 12)));
    return monthlyPayment;    
  }

  /** Find total payment */
  public double getTotalPayment() {
    
    
    double totalPayment = getMonthlyPayment() * numberOfYears * 12;
    return totalPayment;    
  }

  /** Return loan date */
  public java.util.Date getLoanDate() {
    
    
    return loanDate;
  }
  
  public String toString() {
    
    
	  return "Your loan interest is " + getAnnualInterestRate() + ", duration is " + getNumberOfYears() + ", and amount is " + getLoanAmount();
  }
}

Output result:

Your loan interest is 3.5, duration is 5, and amount is 10000.0
Your loan interest is 4.0, duration is 5, and amount is 20000.0
Your loan interest is 4.5, duration is 5, and amount is 30000.0
Your loan interest is 5.0, duration is 5, and amount is 40000.0
Your loan interest is 5.5, duration is 5, and amount is 50000.0
* 17.7 (restore object from file)

Assume that a file named Exercise17_07.dat has been created using ObjectOutputStream. This file contains Loan objects. The Loan class in Listing 10-2 does not implement Serializable. Rewrite the Loan class to implement Serializable. Write a program to read the Loan object from the file and calculate the total loan amount. Assume that the number of Loan objects in the file is unknown. Use EOFException to end the loop.

The previous question gave the Exercise17_06.dat and Loan.java files, use them as the files for this question

import java.io.*;
import java.util.ArrayList;

public class Test {
    
    
	public static void main(String[] args) {
    
    
		// 全局变量list表示贷款额,sum表示贷款总额
		ArrayList<Double> list = new ArrayList<>();
		double sum = 0;
		
		// 读取这5个对象
		try (ObjectInputStream input = new ObjectInputStream(new FileInputStream("Exercise17_06.dat"))) {
    
    
			while (true) {
    
    
				list.add(((Loan)input.readObject()).getLoanAmount());
			}
		} catch (EOFException e) {
    
    
			System.out.println("End of File");
		} catch (IOException e) {
    
    
			System.out.println("IOException");
		} catch (ClassNotFoundException e) {
    
    
			System.out.println("ClassNotFoundException");
		}
		
		// 计算总额
		for (int i = 0; i < list.size(); i++) {
    
    
			sum = sum + list.get(i);
		}
		System.out.print("Total loan amount is " + sum);
 	}
}

Output result:

End of File
Total loan amount is 150000.0
*17.8 (update counter)

Suppose you want to track the number of times a program is run. An int value can be stored to count the files. Every time the program is executed, the counter is incremented by 1. Name the program Exereise17_08 and store the counters in the file Exercise17_08.dat

import java.io.*;

public class Test {
    
    
    public static void main(String[] args) throws FileNotFoundException {
    
    
    	// 初始化执行次数是0
        int runs = 0;

        File file = new File("Exercise17_08.dat");
        // 如果文件不存在,就意味着文件是第一次执行,所以执行次数是1
        if (!file.exists()) {
    
    
            runs = 1;
            writeFile(runs, file);
        // 如果文件已经存在,就去找过去执行的次数,然后+1代表再执行一次
        } else {
    
    
            runs = readFile(file);
            writeFile(++runs, file);
        }
        System.out.println("Number of runs: " + runs);
    }

    // 找出执行的次数,Exercise17_08.dat只有1个int数字,而这个数字就代表着执行的次数
    static int readFile(File file) {
    
    
        int i = 0;
        try (DataInputStream dIs = new DataInputStream(new FileInputStream(file))) {
    
    
            i = dIs.readInt();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return i;

    }

    // 执行1次,把新的次数写入文件
    static void writeFile(int i, File file) {
    
    
        try (DataOutputStream das = new DataOutputStream(new FileOutputStream(file))) {
    
    
            das.writeInt(i);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
}

Output result:

Number of runs: 33
***17.9 (Address Book)

Write programs to store, return, add, and update the address book shown in Figure 17-20. Use a fixed-length string to store each attribute in the address. Use random access files to read and write to an address. Assume the lengths of name, street, city, state, and zip code are 32, 32, 20, 2, and 5 bytes, respectively

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Exercise17_09 extends Application {
    
    
    static String[] packageParts = Exercise17_09.class.getPackage().getName().split("\\.");
    final static String path = packageParts[0] + File.separator + packageParts[1] + File.separator + "address_store" +
            ".dat";
    static File storage;

    static int pointer;
    static List<String> addresses = new ArrayList<>();

    static final int NAME_SIZE = 32;
    static final int STREET_SIZE = 32;
    static final int CITY_SIZE = 20;
    static final int STATE_SIZE = 2;
    static final int ZIP_SIZE = 5;
    static final int TOTAL = 91;

    static TextField nameField;
    static TextField streetField;
    static TextField cityField;
    static TextField stateField;
    static TextField zipField;

    @Override
    public void start(Stage primaryStage) {
    
    
        storage = new File(path);
        String s = retrieve(storage);
        initAddressList(s);

        VBox rootBox = initUserInterface();
        Scene scene = new Scene(rootBox, 500, 170);

        primaryStage.setTitle("Exercise-17.09");
        primaryStage.setScene(scene);
        primaryStage.setOnCloseRequest(event -> {
    
    
            System.out.println("Window close requested, saving Addresses now...");
            try {
    
    
                store(storage);
            } catch (IOException ioException) {
    
    
                ioException.printStackTrace();
                displayError("Something went wrong storing the address file. Please check the log messages in the " +
                        "console output.");
            }
        });
        primaryStage.setOnShowing(event -> {
    
    
            if (addresses.size() > 0) {
    
    
                setCurrentAddress(addresses.get(0));
            }
        });
        primaryStage.show();
    }

    private void initAddressList(String s) {
    
    
        int len = s.length();
        while (len > 0) {
    
    
            len = len - TOTAL;
            addresses.add(s.substring(len));
            s = s.substring(0, len);
        }
    }

    private VBox initUserInterface() {
    
    
        VBox showBox = new VBox(5.0);

        Label name = new Label("Name");
        Exercise17_09.nameField = new TextField();

        Exercise17_09.nameField.setMinWidth(400);
        HBox topBox = new HBox(name, Exercise17_09.nameField);
        topBox.setSpacing(10);
        topBox.setPadding(new Insets(5, 5, 5, 5));

        showBox.getChildren().add(topBox);

        Label street = new Label("Street");
        Exercise17_09.streetField = new TextField();

        Exercise17_09.streetField.setMinWidth(400);
        HBox midBox = new HBox(street, Exercise17_09.streetField);
        midBox.setSpacing(10);
        midBox.setPadding(new Insets(5, 5, 5, 5));

        showBox.getChildren().add(midBox);

        Label city = new Label("City");
        Exercise17_09.cityField = new TextField();

        HBox h1 = new HBox(city, Exercise17_09.cityField);
        h1.setPadding(new Insets(2, 2, 2, 2));
        h1.setSpacing(10);

        Label state = new Label("State");
        Exercise17_09.stateField = new TextField();

        Exercise17_09.stateField.setMaxWidth(45);

        HBox h2 = new HBox(state, Exercise17_09.stateField);
        h2.setPadding(new Insets(2, 2, 2, 2));
        h2.setSpacing(10);

        Label zip = new Label("Zip");
        Exercise17_09.zipField = new TextField();

        Exercise17_09.zipField.setMaxWidth(65);
        HBox h3 = new HBox(zip, Exercise17_09.zipField);
        h3.setPadding(new Insets(2, 2, 2, 2));
        h3.setSpacing(10);

        HBox bottomBox = new HBox(h1, h2, h3);
        bottomBox.setAlignment(Pos.CENTER);

        showBox.getChildren().add(bottomBox);

        Button addButton = new Button("Add");
        addButton.setOnAction(event -> add());

        Button firstButton = new Button("First");
        firstButton.setOnAction(event -> first());

        Button nextButton = new Button("Next");
        nextButton.setOnAction(event -> next());

        Button previousButton = new Button("Previous");
        previousButton.setOnAction(event -> previous());

        Button lastButton = new Button("Last");
        lastButton.setOnAction(event -> last());

        Button updateButton = new Button("Update");
        updateButton.setOnAction(event -> update(pointer));
        HBox buttonBox = new HBox(addButton, firstButton, nextButton, previousButton, lastButton, updateButton);
        buttonBox.setSpacing(10.0);
        buttonBox.setAlignment(Pos.CENTER);

        showBox.getChildren().add(buttonBox);

        return showBox;
    }

    static void displayError(String error) {
    
    
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setContentText(error);
        alert.show();
    }

    private void add() {
    
    
        System.out.println(getAddressString());
        addresses.add(getAddressString());
    }

    private void first() {
    
    
        if (addresses.size() > 0) {
    
    
            pointer = 0;
            setCurrentAddress(addresses.get(pointer));
        } else {
    
    
            displayError("Create an address to add to the list.");
        }

    }

    private void next() {
    
    
        if (pointer < addresses.size() - 1) {
    
    
            ++pointer;
            setCurrentAddress(addresses.get(pointer));
        } else {
    
    
            displayError("End of address list reached.");
        }

    }

    private void previous() {
    
    
        if (pointer > 0) {
    
    
            --pointer;
            setCurrentAddress(addresses.get(pointer));
        } else {
    
    
            displayError("Beginning of address list reached.");

        }
    }

    private void last() {
    
    
        setCurrentAddress(addresses.get(addresses.size() - 1));
    }

    private void setCurrentAddress(String fixLenStr) {
    
    
        Exercise17_09.nameField.setText(fixLenStr.substring(0, 32));
        Exercise17_09.streetField.setText(fixLenStr.substring(32, 64));
        Exercise17_09.cityField.setText(fixLenStr.substring(64, 84));
        Exercise17_09.stateField.setText(fixLenStr.substring(84, 86));
        Exercise17_09.zipField.setText(fixLenStr.substring(86));

    }

    private void update(int pointer) {
    
    
        addresses.set(pointer, getAddressString());
        displayInfo("Updated the address!");

    }

    private void displayInfo(String updated) {
    
    
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setContentText(updated);
        alert.show();
    }

    protected void store(File f) throws IOException {
    
    
        boolean b = false;
        if (!f.exists()) {
    
    
            try {
    
    
                b = f.createNewFile();
            } catch (Exception e) {
    
    
                try {
    
    
                    f.setWritable(true);
                    b = f.createNewFile();
                } catch (Exception ex) {
    
    
                    ex.printStackTrace();
                }
            }
        }

        try {
    
    
            RandomAccessFile raf = new RandomAccessFile(f, "rw");
            for (String address : addresses) {
    
    
                raf.writeUTF(address);
            }

            raf.close();

        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

    protected String retrieve(File file) {
    
    
        String read = "";
        if (!file.exists()) {
    
    
            try {
    
    
                file.createNewFile();
            } catch (IOException e) {
    
    
                displayError("File does note exist and encountered an error while creating it.");
            }
        } else {
    
    
            try {
    
    
                RandomAccessFile raf = new RandomAccessFile(file, "r");
                while (true) {
    
    
                    read = read.concat(raf.readUTF());
                }

            } catch (EOFException eof) {
    
    
                System.out.println("End of File reached!");
                return read;
            } catch (IOException ioException) {
    
    
                displayError(ioException.getMessage());
            }
        }
        return read;
    }

    protected String getAddressString() {
    
    
        String address = "";
        String name = nameField.getText();

        for (int i = name.length(); i < NAME_SIZE; i++) {
    
    
            name += " ";
        }
        address += name;

        String street = streetField.getText();
        for (int i = street.length(); i < STREET_SIZE; i++) {
    
    
            street += " ";
        }
        address += street;

        String city = cityField.getText();
        for (int i = city.length(); i < CITY_SIZE; i++) {
    
    
            city += " ";
        }
        address += city;

        String state = stateField.getText();
        for (int i = state.length(); i < STATE_SIZE; i++) {
    
    
            state += " ";
        }
        address += state;

        String zip = zipField.getText();

        for (int i = zip.length(); i < ZIP_SIZE; i++) {
    
    
            zip += " ";
        }
        address += zip;

        return address;
    }
}

Output result:

insert image description here

*17.10 (split file)

Suppose you want to back up a large file (for example, a 10GB AVI file) on a CD-R. You can split the file into several smaller pieces and back them up independently. Write a utility program that splits a large file into smaller files using the following command:

java Exercisel7_10 SourceFile numberOfPieces

This command creates files SourceFile.1, SourceFile.2, •••, SourceFile.n, where n is numberOfPieces and the output files are roughly the same size.

import java.io.*;

public class Test {
    
    
    public static void main(String[] args) throws IOException {
    
    
    	String file = args[0];
    	int pieces = Integer.parseInt(args[1]);
    	// 因为要输出给n个文件片段,这里用一个index来表示文件片段的文件名,第一个文件名是1
    	int fileIndex = 1;
    	
    	// 读取大文件的所有字符,并平均分配给若干文件片段
    	try (RandomAccessFile ral = new RandomAccessFile(file, "r")) {
    
    
    		// 大文件的字节数
    		long totalLength = ral.length();
    		// 根据指定的片段个数,算出每个片段应该包含的字节数,+1是为了避免大文件的最后几个字符无法写入文件片段
    		long singleLength = totalLength / pieces + 1;
    		// 一会会用到read(b: byte[])方法,先声明一下参数
    		byte[] buffer;
    		
    		// 因为初始化buffer的时候需要指定大小,这个大小是用int形式的数字表示的,如果它超过了int能表示的最大范围,程序就会报错了
    		if (singleLength < Integer.MAX_VALUE && singleLength > Integer.MIN_VALUE) {
    
    
    			// 根据片段大小,初始化buffer数组
    			buffer = new byte[(int)singleLength];
    			// 把singleLength大小的字节写入buffer数组,同时把写入的字节长度保存到bytesRead中,这个方法默认,如果文件中剩余的字节大于等于buffer数据长度,就写入buffer数组长度个字节,如果小于,就直接写完剩下所有的
    			int bytesRead = ral.read(buffer);
    			// 如果读取没有结束
    			while (bytesRead != -1) {
    
    
    				// 一个一个的把字节写入文件片段
    				for (int i = 0; i < bytesRead; i++) {
    
    
    					// 使用fileIndex表示文件名的序列号
    					DataOutputStream output = new DataOutputStream(new FileOutputStream("split" + fileIndex + ".txt", true));
    					output.writeChar((char)buffer[i]);
    					output.close();
    			    }
    				bytesRead = ral.read(buffer);
    				// 写完一个片段,就更换下一个片段
    				fileIndex++;
    			}
    		// 超出范围,程序异常退出
    		} else {
    
    
    			System.out.println("Casting Out Of Bound");
    			System.exit(1);
    		}
    		
    		// 提示程序运行成功
    		// 我的mac zsh命令行,如果字符串没有换行符,会自己加上一个%,所以我这里打印println换行,就不会有%了
    		System.out.println("Done!");
    	}
    }
}

Output result:

(base) kevinwang@KevindeMacBook-Pro ~ % java /Users/kevinwang/Eclipse/test/src/Test.java /Users/kevinwang/Eclipse/test/Exercise17_10.txt 4
Done!

insert image description here

**17.11 (Split file tool with GUI)

Rewrite Exercise 17.10 to include a GUI, as shown in Figure 17-21a.

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.io.*;

public class Test extends Application {
    
    
    @Override
    public void start(Stage pStage) {
    
    
        VBox vBox = new VBox();

        Text text = new Text("If you split a file into 3 smaller files,\nthe 3 smaller files are split1.txt, split2.txt, split3.txt.");

        GridPane gridPane = new GridPane();
        Text hit1 = new Text("Enter a file: ");
        TextField fileNameField = new TextField();
        Text hit2 = new Text("Specify the number of smaller files: ");
        TextField numPiecesField = new TextField();
        gridPane.add(hit1, 0, 0);
        gridPane.add(fileNameField, 1, 0);
        gridPane.add(hit2, 0, 1);
        gridPane.add(numPiecesField, 1, 1);

        Button button = new Button("Start");

        vBox.getChildren().addAll(text, gridPane, button);
        VBox.setMargin(text, new Insets(5, 5, 5, 5));
        VBox.setMargin(gridPane, new Insets(5, 5, 5, 5));
        VBox.setMargin(button, new Insets(5, 5, 5, 130));

        button.setOnAction(e -> {
    
    
            try {
    
    
                String[] args = new String[2];
                args[0] = fileNameField.getText();
                args[1] = numPiecesField.getText();
                split(args);
            } catch (IOException exception) {
    
    
                exception.printStackTrace();
            }
        });

        Scene scene = new Scene(vBox, 300, 150);
        pStage.setTitle("Split Test");
        pStage.setScene(scene);
        pStage.show();
    }

    public static void split(String[] args) throws IOException {
    
    
        String file = args[0];
        int pieces = Integer.parseInt(args[1]);
        // 因为要输出给n个文件片段,这里用一个index来表示文件片段的文件名,第一个文件名是1
        int fileIndex = 1;

        // 读取大文件的所有字符,并平均分配给若干文件片段
        try (RandomAccessFile ral = new RandomAccessFile(file, "r")) {
    
    
            // 大文件的字节数
            long totalLength = ral.length();
            // 根据指定的片段个数,算出每个片段应该包含的字节数,+1是为了避免大文件的最后几个字符无法写入文件片段
            long singleLength = totalLength / pieces + 1;
            // 一会会用到read(b: byte[])方法,先声明一下参数
            byte[] buffer;

            // 因为初始化buffer的时候需要指定大小,这个大小是用int形式的数字表示的,如果它超过了int能表示的最大范围,程序就会报错了
            if (singleLength < Integer.MAX_VALUE && singleLength > Integer.MIN_VALUE) {
    
    
                // 根据片段大小,初始化buffer数组
                buffer = new byte[(int)singleLength];
                // 把singleLength大小的字节写入buffer数组,同时把写入的字节长度保存到bytesRead中,这个方法默认,如果文件中剩余的字节大于等于buffer数据长度,就写入buffer数组长度个字节,如果小于,就直接写完剩下所有的
                int bytesRead = ral.read(buffer);
                // 如果读取没有结束
                while (bytesRead != -1) {
    
    
                    // 一个一个的把字节写入文件片段
                    for (int i = 0; i < bytesRead; i++) {
    
    
                        // 使用fileIndex表示文件名的序列号
                        DataOutputStream output = new DataOutputStream(new FileOutputStream("split" + fileIndex + ".txt", true));
                        output.writeChar((char)buffer[i]);
                        output.close();
                    }
                    bytesRead = ral.read(buffer);
                    // 写完一个片段,就更换下一个片段
                    fileIndex++;
                }
                // 超出范围,程序异常退出
            } else {
    
    
                System.out.println("Casting Out Of Bound");
                System.exit(1);
            }

            // 提示程序运行成功
            // 我的mac zsh命令行,如果字符串没有换行符,会自己加上一个%,所以我这里打印println换行,就不会有%了
            System.out.println("Done!");
        }
    }
}

Output result:

insert image description here

*17.12 (Assembled file)

Write a utility program that combines files together to form a new file using the following command:

java Exercisel7_12 SourceFlle1 ... SourceFileN TargetFile

This command merges SourceFile1, …, SourceFileN into TargetFile

See 17.13

*17.13 (Compose file tool with GUI)

Rewrite programming exercise 17.12 to have a GUI, as shown in Figure 1721b

17.12 and 17.13 are essentially the same, here we directly draw the 17.13GUI

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.io.*;

public class Test extends Application {
    
    
    @Override
    public void start(Stage pStage) {
    
    
        VBox vBox = new VBox();

        Text text = new Text("If the base file is named temp.txt with 3 pieces,\nsplit1.txt, split2.txt, split3.txt are combined into temp.txt");

        GridPane gridPane = new GridPane();
        Text hit1 = new Text("Enter a file: ");
        TextField fileNameField = new TextField();
        Text hit2 = new Text("Specify the number of smaller files: ");
        TextField numPiecesField = new TextField();
        gridPane.add(hit1, 0, 0);
        gridPane.add(fileNameField, 1, 0);
        gridPane.add(hit2, 0, 1);
        gridPane.add(numPiecesField, 1, 1);

        Button button = new Button("Start");

        vBox.getChildren().addAll(text, gridPane, button);
        VBox.setMargin(text, new Insets(5, 5, 5, 5));
        VBox.setMargin(gridPane, new Insets(5, 5, 5, 5));
        VBox.setMargin(button, new Insets(5, 5, 5, 130));

        button.setOnAction(e -> {
    
    
            try {
    
    
                String[] args = new String[2];
                args[0] = fileNameField.getText();
                args[1] = numPiecesField.getText();
                combine(args);
            } catch (IOException exception) {
    
    
                exception.printStackTrace();
            }
        });

        Scene scene = new Scene(vBox, 320, 150);
        pStage.setTitle("Split Test");
        pStage.setScene(scene);
        pStage.show();
    }

    public static void combine(String[] args) throws IOException {
    
    
        String file = args[0];
        int pieces = Integer.parseInt(args[1]);
        // 因为要输出给n个文件片段,这里用一个index来表示文件片段的文件名,第一个文件名是1
        int fileIndex = 1;

        for (; fileIndex <= pieces; fileIndex++) {
    
    
            DataOutputStream output = new DataOutputStream(new FileOutputStream(file, true));
            DataInputStream input = new DataInputStream(new FileInputStream("split" + fileIndex + ".txt"));
            int bytes = input.read();
            while (bytes != -1) {
    
    
                output.write((char)bytes);
                bytes = input.read();
            }
        }

        System.out.println("Done!");
        }
    }

Output result:

insert image description here

17.14 (encrypted files)

Encode the file by adding 5 to each byte in the file. Write a program that prompts the user for an input file name and an output file name, and then saves an encrypted version of the input file to the output file.

package com.example.demo;

import java.io.*;

public class Test {
    
    
    public static void main(String[] args) throws IOException {
    
    
        // 原始文件
        String originalFile = args[0];
        // 加密文件
        String encryptFile = args[1];

        DataOutputStream output = new DataOutputStream(new FileOutputStream(encryptFile, true));
        DataInputStream input = new DataInputStream(new FileInputStream(originalFile));
        int bytes = input.read();
        while (bytes != -1) {
    
    
            output.write((char)(bytes + 5));
            bytes = input.read();
        }

        System.out.println("Done!");
    }
}

Output result:

(base) kevinwang@KevindeMacBook-Pro demo % java /Users/kevinwang/IDEA/demo/src/main/java/com/example/demo/Test.java /Users/kevinwang/IDEA/demo/origin.txt /Users/kevinwang/IDEA/demo/final.txt
Done!

insert image description here

17.15 (Decrypted files)

Suppose the file is encrypted with the encoding scheme in Programming Exercise 17.14. Write a program to decode this encrypted file. The program should prompt the user for an input file name and an output file name, and then save the decrypted version of the input file to the output file.

package com.example.demo;

import java.io.*;

public class Test {
    
    
    public static void main(String[] args) throws IOException {
    
    
        // 密码文件
        String passwordFile = args[0];
        // 解密以后的文件
        String afterDecryptionFile = args[1];

        DataOutputStream output = new DataOutputStream(new FileOutputStream(afterDecryptionFile, true));
        DataInputStream input = new DataInputStream(new FileInputStream(passwordFile));
        int bytes = input.read();
        while (bytes != -1) {
    
    
            output.write((char)(bytes - 5));
            bytes = input.read();
        }

        System.out.println("Done!");
    }
}

Output result:

(base) kevinwang@KevindeMacBook-Pro demo % java /Users/kevinwang/IDEA/demo/src/main/java/com/example/demo/Test.java /Users/kevinwang/IDEA/demo/password.txt /Users/kevinwang/IDEA/demo/decryption.txt
Done!

insert image description here

17.16 (frequency of characters)

Write a program that prompts the user for the name of an ASCII text file and then displays the frequency of occurrence of each character in the file.

package com.example.demo;

import java.io.File;
import java.io.FileInputStream;
import java.util.Scanner;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Scanner in = new Scanner(System.in);
        System.out.print("Enter the name of an ASCII text file: ");
        String fileName = in.next();
        if (!fileName.isEmpty()) {
    
    
            File file = new File(fileName);
            int totalChars = 0;
            int totalLines = 1;
            try (FileInputStream fileInputStream = new FileInputStream(file)) {
    
    
                int nextChar;
                while ((nextChar = fileInputStream.read()) != -1) {
    
    
                    char ch = (char) nextChar;
                    if (ch != ' ') {
    
    
                        totalChars++;
                    }
                    if (ch == '\n') {
    
    
                        totalLines++;
                    }
                }
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }

            System.out.println("There are " + totalChars + " total characters in the file.");
            System.out.println("There are " + totalLines + " total lines in the file.");
            System.out.println("So the file has an average of " + totalChars / totalLines + " characters per line.");
        } else {
    
    
            System.out.println("Please enter a file name in the prompt...");
            System.exit(1);
        }
        in.close();
    }
}

Output result:

Enter the name of an ASCII text file: Exercise17_16.txt
There are 92 total characters in the file.
There are 1 total lines in the file.
So the file has an average of 92 characters per line.
**17.17(BitOutputStream)

Implement a class called BitOutputStream, as shown in Figure 17-22, to write bits to an output stream. The method writeBit(char bit) stores a bit in the form of a byte variable. When creating a BitOutputStream, this byte is empty. After calling writeBit("1"), this byte becomes 00000001. After calling writeBit("0101"), this byte becomes 00010101. The first three bytes are not filled yet. When the bytes are full, they are sent to the output stream. Now the bytes are reset to null. The stream must be closed by calling the close() method. If the byte is neither empty nor full, the close() method will first fill in 0s so that all 8 bits of the byte are filled, then output the byte and close the stream. See editing exercise 5.44 for hints. Write a test program that sends bits 010000100100001001101 to a file called Exercise17_17.dat

Test.java

package com.example.demo;

import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) {
        File testFile = new File("Exercise17_17.txt");
        try {
            BitOutputStream bitOutputStream = new BitOutputStream(testFile);
            bitOutputStream.writeBit("010000100100001001101");
            bitOutputStream.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }
}

BitOutputStream.java

package com.example.demo;

import java.io.*;

public class BitOutputStream implements Closeable {
    
    
    private int value;
    private FileOutputStream fileOutputStream;
    private int posCounter = 0;
    private File file;

    public BitOutputStream(File file) throws FileNotFoundException {
    
    
        this.file = file;
        fileOutputStream = new FileOutputStream(file);
    }

    public void writeBit(char bit) {
    
    
        if (isValid(bit)) {
    
    
            posCounter++;
            value = value << 1; // Shift over bit values to left by one. For Example: (00001111 << 1) = 00011110
            if (bit == '1') {
    
     // If bit is '1' perform logic to change right-most 0 to 1
                value = value | 1; // Use bit masking to turn the last bit on.
            }
            // Check if value is full (when posCounter is 8), if so, write to file and reset aByte
            if (posCounter == 8) {
    
     // value is full (Bit at position 8 is always 0 (non-negative))
                try {
    
    
                    System.out.println("Byte value is full, writing to FileOutputStream: " + Integer.toBinaryString(value));
                    fileOutputStream.write(value); // Write to OutputStream
                    posCounter = 0; // Reset capacity counter to zero
                    value = 0;
                } catch (IOException ioException) {
    
    
                    System.out.println("Error: internal fileOutputStream through exception. Please check you are using " +
                            "correct 'file' parameter.");
                    ioException.printStackTrace();
                }
            }

            // Print the value result formatted as a String for clarity
//            System.out.println("bit is " + bit + " -> value is " + Integer.toBinaryString(aByte));
        } else {
    
    
            throw new IllegalArgumentException("writeBit method only excepts char parameters of '0' or '1' ");
        }
    }

    private boolean isValid(char bit) {
    
    
        return bit == '0' ||
                bit == '1' ||
                bit == '\n' ||
                bit == '\t';
    }

    public void writeBit(String bit) {
    
    
        for (int i = 0; i < bit.length(); i++) {
    
    
            writeBit(bit.charAt(i));
        }
    }

    @Override
    public void close() throws IOException {
    
    
        if (posCounter > 0) {
    
    
            int shift = 8 - posCounter;
            value = value << shift;
            fileOutputStream.write(value);
            System.out.println("Filling rest of the byte value with zeros and writing to FileOutputStream:  " + Integer.toBinaryString(value));
        }
        fileOutputStream.close();
    }
}

Output result:

Byte value is full, writing to FileOutputStream: 1000010
Byte value is full, writing to FileOutputStream: 1000010
Filling rest of the byte value with zeros and writing to FileOutputStream:  1101000
*17.18 (view bits)

Write the following method to display the bit representation of the last byte of an integer. See programming exercise 5.44 for hints. Write a program that prompts the user for a filename, reads bytes from the file, and displays the binary representation of each byte.

package com.example.demo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Scanner;

public class Test {
    
    
    static BufferedInputStream bufferedInputStream;
    static ArrayList<String> strBytes;

    public static void main(String[] args) {
    
    
        Scanner in = new Scanner(System.in);
        strBytes = new ArrayList<>();
        System.out.println("Enter a filename: ");
        String fileName = in.nextLine().trim();
        try {
    
    
            bufferedInputStream = new BufferedInputStream(new FileInputStream(fileName));
            int b;
            while ((b = bufferedInputStream.read()) != -1) {
    
    
                String val = getBits(b);
                strBytes.add(val);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        System.out.println("The contents of the file, converted to bytes are: ");
        System.out.println(strBytes.toString());

        in.close();
    }

    public static String getBits(int value) {
    
    
        StringBuilder bits = new StringBuilder();
        long i;
        for (i = 128; i > 0; i /= 2) {
    
    
            bits.append((value & i) != 0 ? "1" : "0");
        }
        return bits.toString();
    }
}

Output result:

Enter a filename: 
Exercise17_17.txt
The contents of the file, converted to bytes are: 
[01000010, 01000010, 01101000]
*17.19 (view hexadecimal)

Write a program that prompts the user for a filename, reads bytes from the file, and displays the hexadecimal representation of each byte.

package com.example.demo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Scanner;

public class Test {
    
    
    static BufferedInputStream bufferedInputStream;
    static ArrayList<String> strBytes;

    public static void main(String[] args) {
    
    
        Scanner in = new Scanner(System.in);
        strBytes = new ArrayList<>();
        System.out.println("Enter a filename: ");
        String fileName = in.nextLine().trim();
        try {
    
    
            bufferedInputStream = new BufferedInputStream(new FileInputStream(fileName));
            int b;
            while ((b = bufferedInputStream.read()) != -1) {
    
    
                String val = getBits(b);
                System.out.println("Read byte value = " + val);
                int asInteger = Integer.parseInt(val, 2);
                strBytes.add(Integer.toHexString(asInteger).toUpperCase());
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        System.out.println("The byte contents of the file, converted to hex are: ");
        System.out.println(strBytes.toString());
    }

    public static String getBits(int value) {
    
    
        StringBuilder bits = new StringBuilder();
        for (int i = 0; i < 8; i++) {
    
    
            bits.insert(0, (value & 1));
            value >>= 1;
        }
        return bits.toString();
    }
}

Output result:

Enter a filename: 
Exercise17_17.txt
Read byte value = 01000010
Read byte value = 01000010
Read byte value = 01101000
The byte contents of the file, converted to hex are: 
[42, 42, 68]
**17.20 (binary editor)

Write a GUI application that allows the user to enter a file name in the text field, and then click the Enter key to display its binary representation in the text field. Users can also modify this binary code and save it back to this file, as shown in Figure 17-23a.

package com.example.demo;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.*;

public class Test extends Application {
    
    
    private static String filePath = null;
    private SimpleStringProperty editBoxString = new SimpleStringProperty();

    public static void main(String[] args) {
    
    
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
    
    
        VBox mainBox = new VBox(5);
        HBox topBox = new HBox(5);

        TextField textField = new TextField();
        Label label = new Label("Enter a file: ");
        topBox.getChildren().add(label);
        topBox.getChildren().add(textField);
        mainBox.getChildren().add(topBox);

        HBox.setHgrow(textField, Priority.ALWAYS);
        HBox.setMargin(textField, new Insets(5, 5, 5, 1));
        HBox.setMargin(label, new Insets(9, 1, 5, 5));

        TextArea editBox = new TextArea();
        editBox.setWrapText(true);
        editBoxString.bindBidirectional(editBox.textProperty());

        mainBox.getChildren().add(editBox);

        HBox buttonBox = new HBox(5);
        Button saveButton = new Button("Save the change");
        saveButton.setOnAction(e -> {
    
    
            filePath = textField.getText().trim();
            try {
    
    
                writeFile(editBoxString.get(), new File(filePath));
                editBox.clear();
            } catch (IOException ioException) {
    
    
                ioException.printStackTrace();
            }
        });
        buttonBox.setAlignment(Pos.CENTER);
        buttonBox.getChildren().add(saveButton);
        saveButton.setCenterShape(true);

        mainBox.getChildren().add(buttonBox);
        VBox.setMargin(buttonBox, new Insets(5, 5, 5, 5));

        Scene scene = new Scene(mainBox, 600, 300);
        scene.setOnKeyPressed(event -> {
    
    
            if (event.getCode() == KeyCode.ENTER) {
    
    
                try {
    
    
                    filePath = textField.getText().trim();

                    String bytes = readFile(new File(filePath));
                    editBoxString.set(bytes);

                } catch (IOException ioException) {
    
    
                    System.out.println("FilePath: " + filePath);
                    ioException.printStackTrace();
                }
            }
        });

        primaryStage.setScene(scene);
        primaryStage.setTitle(getClass().getName());
        primaryStage.show();

    }

    private void writeFile(String text, File file) throws IOException {
    
    
        BitOutputStream bitOutputStream = new BitOutputStream(file);
        bitOutputStream.writeBit(text);

    }

    private String readFile(File file) throws IOException {
    
    
        BitInputStream bitOutputStream = new BitInputStream(file);
        return bitOutputStream.readAllBytes();
    }

    public static class BitOutputStream implements Closeable {
    
    
        private FileOutputStream output;
        private int value;
        private int count = 0;
        private int mask = 1;

        public BitOutputStream(File file) throws IOException {
    
    
            output = new FileOutputStream(file);
        }

        public void writeBit(char bit) throws IOException {
    
    
            count++;
            value = value << 1;
            if (bit == '1')
                value = value | mask;
            if (count == 8) {
    
    
                output.write(value);
                count = 0;
            }
        }

        public void writeBit(String bitString) throws IOException {
    
    
            for (int i = 0; i < bitString.length(); i++)
                writeBit(bitString.charAt(i));
        }

        @Override
        public void close() throws IOException {
    
    
            if (count > 0) {
    
    
                value = value << (8 - count);
                output.write(value);
            }
            output.close();
        }

        void t() {
    
    
        }

    }

    public static class BitInputStream implements Closeable {
    
    
        private FileInputStream input;
        private String stringValue;
        private static final int EOF = -1;

        public BitInputStream(File file) throws IOException {
    
    
            input = new FileInputStream(file);
        }

        private String readAllBytes() throws IOException {
    
    
            stringValue = "";
            int intValue;
            while ((intValue = input.read()) != EOF) {
    
    
                stringValue += readBits(intValue);
            }
            input.close();
            return stringValue;

        }

        private String readBits(int value) {
    
    
            String bits = "";
            int mask = 1;
            for (int i = 7; i >= 0; i--) {
    
    
                int temp = value >> i;
                int bit = temp & mask;
                bits = bits + bit;
            }
            return bits;
        }

        @Override
        public void close() throws IOException {
    
    
            input.close();
        }
    }
}

Output result:

insert image description here

**17.21 (Hex editor)

Write a GUI application that allows the user to enter a file name in the text field and press the Enter key to display its hexadecimal representation in the text field. The user can also modify the hex code and save it back to this file, as shown in Figure 17-23b.

package com.example.demo;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.*;

public class Test extends Application {
    
    
    private static String filePath = null;
    SimpleStringProperty editBoxString = new SimpleStringProperty();

    @Override
    public void start(Stage primaryStage) throws Exception {
    
    
        VBox mainBox = new VBox(5);
        HBox topBox = new HBox(5);

        TextField textField = new TextField();
        Label label = new Label("Enter a file: ");
        topBox.getChildren().add(label);
        topBox.getChildren().add(textField);
        mainBox.getChildren().add(topBox);

        HBox.setHgrow(textField, Priority.ALWAYS);
        HBox.setMargin(textField, new Insets(5, 5, 5, 1));
        HBox.setMargin(label, new Insets(9, 1, 5, 5));

        TextArea editBox = new TextArea();
        editBox.setWrapText(true);
        editBoxString.bindBidirectional(editBox.textProperty());

        mainBox.getChildren().add(editBox);

        HBox buttonBox = new HBox(5);
        Button saveButton = new Button("Save the change");
        saveButton.setOnAction(e -> {
    
    
            try {
    
    
                write(editBoxString.get(), filePath);
                editBox.clear();
            } catch (IOException ioException) {
    
    
                ioException.printStackTrace();
            }
        });
        buttonBox.setAlignment(Pos.CENTER);
        buttonBox.getChildren().add(saveButton);
        saveButton.setCenterShape(true);

        mainBox.getChildren().add(buttonBox);
        VBox.setMargin(buttonBox, new Insets(5, 5, 5, 5));

        Scene scene = new Scene(mainBox, 600, 300);
        scene.setOnKeyPressed(event -> {
    
    
            if (event.getCode() == KeyCode.ENTER) {
    
    
                try {
    
    
                    filePath = textField.getText().trim();
                    String hexValuesInString = read(filePath);
                    editBoxString.set(hexValuesInString);

                } catch (IOException ioException) {
    
    
                    ioException.printStackTrace();
                }
            }
        });
        primaryStage.setScene(scene);
        primaryStage.setTitle(getClass().getName());
        primaryStage.show();

    }

    private void write(String hexValues, String filePath) throws IOException {
    
    
        FileOutputStream output = new FileOutputStream(filePath);
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
        for (int i = 0; i < hexValues.length(); i += 2) {
    
    
            char value = (char) ((Character.digit(hexValues.charAt(i), 16) << 4) + Character.digit(hexValues.charAt(i + 1), 16));
            writer.write(value);
        }
        writer.close();
    }

    private String read(String filePath) throws IOException {
    
    
        FileInputStream input = new FileInputStream(filePath);
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        String asChars = "";
        int next;
        while ((next = reader.read()) != -1) {
    
    
            asChars += String.format("%H", next);
        }
        input.close();
        return asChars;
    }


    public static void main(String[] args) {
    
    
        Application.launch(args);
    }
}

Output result:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_40020256/article/details/131267720