简体   繁体   中英

What is the best way to read in chars from a text file while ignoring extra spaces from new lines?

I am reading in a text file with the format of a 16x16 sudoku puzzle.

For Example:

F7B-E-A-1--6---D  
-91AF-0-85D7E4-C  
05-69C---B-EA-3-  
-C-E-2-B--A-7860  
E05---2F-7---1C-  
-4-8-DC--E-593--  
-29---1-D--A-04-  
D67-A-98----B-F-  
9B-D-130C8--F5A-  
8F4569EA7D--CB--  
6A---745BFE-12D9  
7--1DBFC-A-04--E  
5-F9C-61240D-7E-  
A--7-F-DE-580-2-  
--0-5E7-F63C--14  
CE640-----7B5D9F

I'm attempting to put the values into a 2D char array, but when encountering the end of a line 3 spaces seem to be included. I've tried using various ways like BufferedReader and FileInputStream to no avail. The text files must be in that format as my professor will be testing with his own values using that format.

My code for getting the file into an ArrayList:

private static ArrayList readFile(File filename)
{
    ArrayList records = new ArrayList();
    try
    {
        FileInputStream stream = new FileInputStream(filename);

        char current;
        while(stream.available() > 0)
        {
            current = (char)stream.read();
            records.add(current);
        }
        stream.close();
        return records;
    }
    catch (Exception e)
    {
        System.err.format("Exception occurred trying to read '%s'.", filename);
        return null;
    }
}

I then use an iterator to start assigning values to the 2D array. When printing out the grid it appears fine, but when checking individual values, like grid[1][1], it's not right because of the spacing it throws in.

Is there a way to read in char by char, but avoid the 3 spaces it puts in to represent the new line?

You mention that you want to put in a 2D char array, so you might want to ignore the position > 15 :

char[][] sudoku = new char[16][16];
Scanner sc = new Scanner(filename);
String[] temporary = new String[16];
int counter = 0;

while(sc.hasNext){
    temporary[counter] = sc.nextLine();
    counter ++;
}

for(int i = 0; i < 16; i++){
    for(int j = 0; j < 16; j++){
        sudoku[i][j] = temporary[i].charAt(j);
    }
}

Now your 2d array will automatically ignore those blank at the end because you read in the file line by line, and you add in the value into the 2d array manually.

Well, since you're only really interested in hexadecimal characters and - , you can just filter everything else out. The easiest way is probably to replace:

current = (char)stream.read();

with:

current = (char)stream.read();
while ("0123456789ABCDEF-".indexOf(current) < 0)
    current = (char)stream.read();

but you may need to fiddle with error conditions to ensure it's bullet-proof.

For example, check how many elements were added to records once your input loop finishes. If records.size() doesn't give you 256, the file was faulty.

That would remove all formatting concerns from your file and only content will matter (if you want, you can just provide all 256 characters on a single line, for example).

This follows the robustness principle of "be liberal in what you accept, specific in what you produce".


You may also want to rethink your method of creating an array list from the file input and then constructing a two-dimensional array from that. It seems to me you can just create the 2D array directly with something like (pseudo-code):

def readPuzzle(file) -> (array, error)
    set puzzle to new char[16][16]
    set row to 0, col to 0

    get next character from file to current
    while read okay:
        if current in "0123456789ABCDEF-":
            if row is 16:
                return (puzzle, "too many entries in file")
            puzzle[row][col] = current
            increment col
            if col is 16:
                increment row
                set col to 0
    if row is not 16:
        return (puzzle, "not enough entries in file")
    return (puzzle, "okay")

This basically just reads all characters from the file and adds them directly to the array if they're valid. Before adding, it checks to ensure you haven't already filled the puzzle and, after all characters are processed, it checks to ensure the whole puzzle was filled.

String.trim() is the simplest way to remove unnecessary whitespace from the beginning or end of a string, so you can always just do a cleanup pass once you've read the file:

private static void trimAllStrings(List<String> list) {
  for (int i = 0; i < list.size(); i++) {
    list.put(i, list.get(i).trim());
  }
}

Or you can do the trimming while reading the contents in - Java 8's Files.lines() stream makes this sort of transformation really easy:

List<String> trimmedLines = Files.lines(myfile, StandardCharsets.UTF_8)
    .map(String::trim).collect(Collectors.toList());

If you haven't gotten to this Java 8 syntax yet you can do basically the same thing in Java 7 style:

ArrayList<String> list = new ArrayList<>();
for (String line : Files.readAllLines(myfile, StandardCharsets.UTF_8)) {
  list.add(line.trim());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM