0

我用 java 制作了一个简单的解析器,它一次读取一个字符并构造单词。

我尝试在 Linux 下运行它,我注意到寻找'\n'不起作用。虽然如果我将字符与值进行比较,10它会按预期工作。根据 ASCII 表值 10 是 LF(换行)。我在某处(我不记得在哪里)读到 Java 应该只能通过查找来找到换行符'\n'

我正在使用BufferedReaderread读取字符的方法。

编辑

readLine不能使用,因为会产生其他问题

当我在 linux 下使用带有 mac/windows 文件结尾的文件时,似乎出现了问题。

4

3 回答 3

2

用于readLine()逐行阅读文本

例子

FileInputStream fstream = new FileInputStream("textfile.txt");
  // Get the object of DataInputStream
  DataInputStream in = new DataInputStream(fstream);
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  String strLine;
  //Read File Line By Line
  while ((strLine = br.readLine()) != null)   {
  // Print the content on the console
  System.out.println (strLine);
  }
  //Close the input stream
  in.close();
    }catch (Exception e){//Catch exception if any
  System.err.println("Error: " + e.getMessage());
  }
于 2012-01-02T12:16:54.313 回答
1

如果您逐字节读取文件,则必须处理所有 3 种情况 '\n' 用于 Linux,“\r\n” 用于 Windows 和 '\r' 用于 mac。

请改用 readLine 方法。它会为您处理这些事情,并且只返回没有任何终止符的线路。阅读每一行后,您可以对其进行标记以获得单个单词。

还要考虑使用系统属性“line.separator”。它始终拥有依赖于系统的行终止符,至少使您的代码(而不是生成的文件)更加门户。

于 2012-01-02T12:11:32.380 回答
1

这里有两种方法可以做到

1-使用逐行读取并使用正则表达式拆分每个单词以获取单个单词

2-编写自己的 isDelimiter 方法并使用它来检查是否达到拆分条件

package misctests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;


public class SplitToWords {

    String someWords = "Lorem ipsum\r\n(dolor@sit)amet,\nconsetetur!\rsadipscing'elitr;sed~diam";
    String delimsRegEx = "[\\s;,\\(\\)!'@~]+";
    String delimsPlain = ";,()!'@~"; // without whitespaces

    String[] expectedWords = {
        "Lorem",
        "ipsum",
        "dolor",
        "sit",
        "amet",
        "consetetur",
        "sadipscing",
        "elitr",
        "sed",
        "diam"
    };

    private static final class StringReader {
        String input = null;
        int pos = 0;
        int len = 0;
        StringReader(String input) {
            this.input = input == null ? "" : input;
            len = this.input.length();
        }

        public boolean hasMoreChars() {
            return pos < len;
        }

        public int read() {
            return hasMoreChars() ? ((int) input.charAt(pos++)) : 0;
        }
    }

    @Test
    public void splitToWords_1() {
        String[] actual = someWords.split(delimsRegEx);
        assertEqualsWords(expectedWords, actual);
    }

    @Test
    public void splitToWords_2() {
        StringReader sr = new StringReader(someWords);
        List<String> words = new ArrayList<String>();
        StringBuilder sb = null;
        int c = 0;
        while(sr.hasMoreChars()) {
            c = sr.read();
            while(sr.hasMoreChars() && isDelimiter(c)) {
                c = sr.read();
            }
            sb = new StringBuilder();
            while(sr.hasMoreChars() && ! isDelimiter(c)) {
                sb.append((char)c);
                c = sr.read();
            }
            if(! isDelimiter(c)) {
                sb.append((char)c);
            }
            words.add(sb.toString());
        }

        String[] actual = new String[words.size()];
        words.toArray(actual);

        assertEqualsWords(expectedWords, actual);
    }

    private boolean isDelimiter(int c) {
        return (Character.isWhitespace(c) ||
            delimsPlain.contains(new String(""+(char)c))); // this part is subject for optimization
    }

    private void assertEqualsWords(String[] expected, String[] actual) {
        assertNotNull(expected);
        assertNotNull(actual);
        assertEquals(expected.length, actual.length);
        for(int i = 0; i < expected.length; i++) {
            assertEquals(expected[i], actual[i]);
        }
    }
}
于 2012-01-02T13:41:30.630 回答