Java读取文件得到了领先的BOM []

时间:2011-06-09 08:49:57

标签: java csv unicode character-encoding java-io

我正在逐行阅读包含关键字的文件,发现一个奇怪的问题。 如果内容相同,我希望相互跟随的行,它们只应处理一次。喜欢

sony
sony

只有第一个正在处理中。 但问题是,java并没有将它们视为平等。

INFO: [, s, o, n, y]
INFO: [s, o, n, y]

我的代码如下所示,问题出在哪里?

    FileReader fileReader = new FileReader("some_file.txt");
    BufferedReader bufferedReader = new BufferedReader(fileReader);
    String prevLine = "";
    String strLine
    while ((strLine = bufferedReader.readLine()) != null) {
        logger.info(Arrays.toString(strLine.toCharArray()));
        if(strLine.contentEquals(prevLine)){
            logger.info("Skipping the duplicate lines " + strLine);
            continue;
        }
        prevLine = strLine;
    }

更新

似乎第一行中有一个空格,但实际上没有,trim方法对我不起作用。他们不一样:

INFO: [, s, o, n, y]
INFO: [ , s, o, n, y]

我不知道java添加的第一个Char是什么。

已解决:问题已通过BalusC's solution解决,感谢您指出它的BOM问题,这有助于我快速找到解决方案。

6 个答案:

答案 0 :(得分:1)

尝试在读取行的开头和结尾处修剪空格。只需用以下内容替换你的时间:

while ((strLine = bufferedReader.readLine()) != null) {
        strLine = strLine.trim();
        logger.info(Arrays.toString(strLine.toCharArray()));
    if(strLine.contentEquals(prevLine)){
        logger.info("Skipping the duplicate lines " + strLine);
        continue;
    }
    prevLine = strLine;
}

答案 1 :(得分:0)

如果空格在处理中不重要,那么每次都可能需要进行strLine.trim()调用。这就是我在处理这样的输入时通常所做的事情 - 如果必须手动编辑空间,空间很容易蔓延到文件中,如果它们不重要,它们可以而且应该被忽略。

编辑:编码为UTF-8的文件?打开文件时,可能需要指定编码。它可能是字节顺序标记或类似的东西,如果它发生在第一行。

尝试:

BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"))

答案 2 :(得分:0)

开头必须有space或某些不可打印的字符。因此,要么在比较期间/之前修正或修剪Strings

<强> [编辑]

如果String.trim()无济于事。使用正确的String.replaceAll()尝试regex。试试这个,str.replaceAll("\\p{Cntrl}", "")

答案 3 :(得分:0)

文件的编码是什么?

文件开头的看不见的字符可以是Byte Order Mark

使用ANSI或UTF-8保存而不使用BOM可以帮助您突出显示此内容。

答案 4 :(得分:0)

我在之前的项目中遇到过类似的情况。罪魁祸首是Byte order mark,我不得不摆脱它。最终我实施了基于this example的黑客攻击。看看,可能是你有同样的问题。

答案 5 :(得分:0)

字节顺序标记 BOM是一个Unicode字符。您将在文本流的开头获得之类的字符,因为 BOM使用是可选的,如果使用,则应出现在文本流的开头

  • Microsoft编译器和解释器,以及Microsoft Windows上的许多软件,例如 Notepad将BOM视为必需的幻数 ,而不是使用启发式。这些工具在将文本保存为UTF-8时添加BOM,除非BOM存在或文件仅包含ASCII,否则无法解释UTF-8。在将文档转换为纯文本文件以供下载时,Google文档还会添加BOM。
File file = new File( csvFilename );
FileInputStream inputStream = new FileInputStream(file);
// [{"Key2":"21","Key1":"11","Key3":"31"} ]
InputStreamReader inputStreamReader = new InputStreamReader( inputStream, "UTF-8" );

我们可以通过将字符串显式指定为UTF-8来解决InputStreamReader。然后在UTF-8中,字节序列  解码为一个字符,即U + FEFF( ? )。

使用Google Guava's jar CharMatcher,您可以删除所有不可打印的字符,然后保留所有ASCII字符(删除任何重音符号),例如this

String printable = CharMatcher.INVISIBLE.removeFrom( input );
String clean = CharMatcher.ASCII.retainFrom( printable );

CSV文件到JSON对象

读取数据的完整示例
public class CSV_FileOperations {
    static List<HashMap<String, String>> listObjects = new ArrayList<HashMap<String,String>>();
    protected static List<JSONObject> jsonArray = new ArrayList<JSONObject >();

    public static void main(String[] args) {
        String csvFilename = "D:/Yashwanth/json2Bson.csv";

        csvToJSONString(csvFilename);
        String jsonData = jsonArray.toString();
        System.out.println("File JSON Data : \n"+ jsonData);
    }

    @SuppressWarnings("deprecation")
    public static String csvToJSONString( String csvFilename ) {
        try {
            File file = new File( csvFilename );
            FileInputStream inputStream = new FileInputStream(file);

            String fileExtensionName = csvFilename.substring(csvFilename.indexOf(".")); // fileName.split(".")[1];
            System.out.println("File Extension : "+ fileExtensionName);

            // [{"Key2":"21","Key1":"11","Key3":"31"} ]
            InputStreamReader inputStreamReader = new InputStreamReader( inputStream, "UTF-8" );

            BufferedReader buffer = new BufferedReader( inputStreamReader );
            Stream<String> readLines = buffer.lines();
            boolean headerStream = true;

            List<String> headers = new ArrayList<String>();
            for (String line : (Iterable<String>) () -> readLines.iterator()) {
                String[] columns = line.split(",");
                if (headerStream) {
                    System.out.println(" ===== Headers =====");

                    for (String keys : columns) {
                        //  - UTF-8 - ? « https://stackoverflow.com/a/11021401/5081877
                        String printable = CharMatcher.INVISIBLE.removeFrom( keys );
                        String clean = CharMatcher.ASCII.retainFrom(printable);
                        String key = clean.replace("\\P{Print}", "");
                        headers.add( key );
                    }
                    headerStream = false;
                    System.out.println(" ===== ----- Data ----- =====");
                } else {
                    addCSVData(headers, columns );
                }
            }
            inputStreamReader.close();
            buffer.close();


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    @SuppressWarnings("unchecked")
    public static void addCSVData( List<String> headers, String[] row ) {
        if( headers.size() == row.length ) {
            HashMap<String,String> mapObj = new HashMap<String,String>();
            JSONObject jsonObj = new JSONObject();
            for (int i = 0; i < row.length; i++) {
                mapObj.put(headers.get(i), row[i]);
                jsonObj.put(headers.get(i), row[i]);
            }
            jsonArray.add(jsonObj);
            listObjects.add(mapObj);
        } else {
            System.out.println("Avoiding the Row Data...");
        }
    }
}

json2Bson.csv文件数据。

Key1    Key2    Key3
11  21  31
12  22  32
13  23  33
相关问题