Search code examples
javastringconcatenationfilereaderfileinputstream

String's content retrieved from file disappears during concatenation or equality check


I am making a program that will have to read/write plain text files. I read the text from a file and then process it to separate the string into several components (namely lines and then variable/value). When I try processing some of these components, the content of the string appears to change or disappear temporarily. This code reproduces the problem:

package spriteModder;

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

public class ErrorThing {
    public static void main(String[] args) throws IOException {
        loadFile(new File("settings.config"));
    }
    public static void loadFile(File f) throws IOException {
        FileInputStream fis=new FileInputStream(f);
        int numread=1;
        StringBuilder contentBuilder= new StringBuilder();
        byte[] buffer=new byte[8];
        while(numread>0) {
            numread=fis.read(buffer);
            if(numread==-1){break;}
            contentBuilder.append(new String(buffer, 0, numread));
        }
        String source=contentBuilder.toString();
        System.out.println(source);
        String[] lines=source.split("\n");
        for(String s:lines){
            System.out.println(s);
            String[] a=s.split("=");
            for(String s2:a){
                System.out.println(s2);

                System.out.println(s2+"4");
                System.out.println(s2.equals("true"));
            }

        }
    }
}

This is the output:

 //these three lines are to verify the contents of the settings.config file, which works as expected
outputDir=*here 
lookInSubDirectories=true
inputDir=*here
outputDir=*here //the first line of the file
outputDir //the first component of the line
outputDir4 //the first component of the line after concatenation.
false //checks if the component (w/o concatenation) is equal to "true"
*here //second component of the line
4 //second component of the line after concatenation, which is missing the entire original component
false //checks if the second component of the line is equal to "true"
lookInSubDirectories=true
lookInSubDirectories //the first component of the second line
lookInSubDirectories4
false
true // the second component
4 //this component also disappears during concatenation
false // but also fails the equality check, even though the content is "true"
inputDir=*here
inputDir
inputDir4
false
*here
*here4 //you can see concatenation working on the third line's second component here for some reason
false

the content of settings.config is:

outputDir=*here
lookInSubDirectories=true
inputDir=*here

I've tried changing the size of the byte buffer, using a FileReader instead of a FileInputStream, and using temporary variables with no success. I also circumvented reading the file and just hardcoded the same contents into a string, which prevented the problem. However, reading the contents from a file is a necessity. Concatenation always works when only an empty string ("") is concatenated, but anything else will cause the original contents to disappear in those two lines. The equality check fails regardless of whether .equals or == is used. Using substring() instead of split() to produce the components has no effect. What is going on? Why would concatenation cause the original string to disappear in the result, but only sometimes? Why won't the equality check work?


Solution

  • Okay, so nothing disapopears here, and your program works correctly, even if written in unnecessarily cumbersome way. It's easiest to check that just by leaving this line:

     System.out.println(s2);
    

    as the only output on your split String iteration. The only error is in conclusion that something 'disappears'. I'm going to take a wild guess and say you run this code on Windows, or otherwise have your settings.config file's line breaks as \r\n instead of just \n. So, splitting on just \n leaves the hanging \rs, so you have:

    "*here\r" + "4"
    

    and this gets printed as

    *here
    4
    

    Best to check that hanging \rs using a debugger or an if statement.

    So, your program works as much as splitting abc=123 to "abc" and "123" is concerned (or, rather to "abc" and "123\r"). But do consider using Java's built-in method for loading Properties from a file, or at the very least usea BufferedReader, I think it's readLine method will consume both carriage return and line feed characters.