Reading a text file character by character into a

2019-08-13 18:39发布

问题:

As part of my Object Oriented class, we are to design a Battleship game which uses a TUI to eventually implement a GUI. According to the design, we are to read the AI's ship locations from a text file that will look similar to the one b

 ABCDEFGHIJ
1
2 BBBB
3
4       C
5D      C
6D
7AAAAA
8     SSS  
9
0

Where the letters represent different ships. My current implementation of the game uses a 2 dimensional array of characters, so I would like to be able to read the text file and create the corresponding 2D array. I've seen a few built in functions that allow you to read the next String or the next Integer, but I just want to read it character by character. Is there a way to do this? Thanks in advance!

回答1:

The simplest way to do this, in my opinion, is to first read the file line-by-line then read those lines character-by-character. By using a built-in utility, you can avoid the complexities of handling new lines because they vary by OS/Editor.

BufferedReader Docs

    BufferedReader fileInput = new BufferedReader(new FileReader("example.txt"));
    String s;
    while ((s = fileInput.readLine()) != null) {
        for (char c : s.toCharArray()) {
            //Read into array
        }
    }
    fileInput.close();


回答2:

Have a look here.You can read character by character in this way. You need to aware of the new lines. http://docs.oracle.com/javase/tutorial/essential/io/charstreams.html



回答3:

//Open file stream
FileReader in = new FileReader("fileName.txt");
BufferedReader br = new BufferedReader(in);

String line = ""; //Declare empty string used to store each line

//Read a single line in the file and store it in "line" variable
//Loop as long as "line" is not null (end of file)
while((line = br.readLine() != null) {
    //Iterate through string until the end
    //Can use a regular loop also
    for(char ch : line.toCharArray()) {
        //Do something with the variable ch
        if(ch == 'B')
            ;
        else if(ch == 'C')
            ;
        else if(ch == ' ')
            ;
        else
            ;
    }
}

The general idea is to break the problem into simpler to solve problems. If you have a function that can open a file and read a single line, then you solved one problem. Next you need to solve the problem of iterating through a string character by character. This can be done multiple ways, but one way is to use the built in functions of the String class to convert the String to a character array.

Only thing missing is the try{} catch{} usually required when opening a file along with correctly importing the classes: FileReader & BufferedReader.



回答4:

@JudgeJohn's answer is good - I would comment but I can't unfortunately. Reading first line by line will ensure that any system details like implementation of line breaks are handled by Java's various libraries, which know how to do that very well. Using a Scanner on some kind of reader over a file will allow easy enumeration over lines. After this, reading the obtained String character by character should not be a problem, for example using the toCharArray() method.

An important addition - when using Stream and Reader objects, and Scanners over them, it's very often important that your code handles the end of the process well - disposing of system resources like file handles. This is done in Java using the close() methods of these classes. Now, if we finish reading and just call close(), this is all very well when things go to plan, but it's possible that Exceptions could be thrown, causing the method to exit before the close() method is called. A good solution is a try - catch or try - finally block. E.g.

Scanner scanner = null;
try {
    scanner = new Scanner(myFileStream);
    //use scanner to read through file
    scanner.close();
} catch (IOException e) {
    if (scanner != null) scanner.close(); //check for null in case scanner never got initialised.
}

Even better is

Scanner scanner = null;
try {
    scanner = new Scanner(myFileStream);
    //use scanner to read through file
} finally {
    if (scanner != null) scanner.close(); //check for null in case scanner never got initialised.
}

The finally block always gets called, regardless of how the try block exits. Even better, there's a try-with-resources block in Java, which goes like this:

try (Scanner scanner = new Scanner(myFileStream)) {
    //use scanner to read through file
}

This one does all the checking for nulls, finally and calling of close(). Very safe, and quick to type!



回答5:

You can use a Scanner to read an individual character like so:

scanner.findInLine(".").charAt(0)

The board is an 11x11 of characters (char[][] board = new char[11][11]), so you'll have to track what row and column you're on as you're reading the characters. You'll know when to go to the next row after you've read the 11th character.

Code Sample:

public static void main(String[] args) throws Exception {
    String file = 
        " ABCDEFGHIJ\n" +
        "1          \n" +
        "2 BBBB     \n" +
        "3          \n" +
        "4       C  \n" +
        "5D      C  \n" +
        "6D         \n" +
        "7AAAAA     \n" +
        "8     SSS  \n" +
        "9          \n" +
        "0          \n";

    char[][] board = new char[11][11];
    Scanner scanner = new Scanner(file);

    int row = 0;
    int col = 0;
    while (scanner.hasNextLine()) {
        // Read in a single character
        char character = scanner.findInLine(".").charAt(0);
        board[row][col] = character;
        col++;

        if (col == 11) {
            // Consume the line break
            scanner.nextLine();

            // Move to the next row
            row++;
            col = 0;    
        }
    }

    // Print the board
    for (int i = 0; i < board.length; i++) {
        System.out.println(new String(board[i]));
    }
}

Results:

 ABCDEFGHIJ
1          
2 BBBB     
3          
4       C  
5D      C  
6D         
7AAAAA     
8     SSS  
9          
0