【问题标题】:How do I read input character-by-character in Java?如何在 Java 中逐个字符地读取输入?
【发布时间】:2010-10-23 03:34:08
【问题描述】:

我习惯了c风格的getchar(),但是好像java没有可比性。我正在构建一个词法分析器,我需要逐个字符地读取输入。

我知道我可以使用扫描仪扫描令牌或行并逐个字符地解析令牌,但这对于跨越多行的字符串来说似乎很笨拙。有没有办法从 Java 的输入缓冲区中获取下一个字符,还是应该直接使用 Scanner 类?

输入是文件,而不是键盘。

【问题讨论】:

标签: java character tokenize


【解决方案1】:

这将从文件中每行打印 1 个字符。

    try {

        FileInputStream inputStream = new FileInputStream(theFile);
        while (inputStream.available() > 0) {
            inputData = inputStream.read();
            System.out.println((char) inputData);

        }
        inputStream.close();
    } catch (IOException ioe) {
        System.out.println("Trouble reading from the file: " + ioe.getMessage());
    }

【讨论】:

    【解决方案2】:

    将您的输入流包装在缓冲读取器中,然后使用 read 方法一次读取一个字节,直到流结束。

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class Reader {
    
        public static void main(String[] args) throws IOException {
    
            BufferedReader buffer = new BufferedReader(
                     new InputStreamReader(System.in));
            int c = 0;
            while((c = buffer.read()) != -1) {
                char character = (char) c;          
                System.out.println(character);          
            }       
        }   
    }
    

    【讨论】:

      【解决方案3】:

      如果我是你,我会使用扫描仪并使用“.nextByte()”。你可以把它转换成一个字符,你很好。

      【讨论】:

        【解决方案4】:

        使用Reader.read()。返回值 -1 表示流结束;否则,转换为 char

        此代码从文件参数列表中读取字符数据:

        public class CharacterHandler {
            //Java 7 source level
            public static void main(String[] args) throws IOException {
                // replace this with a known encoding if possible
                Charset encoding = Charset.defaultCharset();
                for (String filename : args) {
                    File file = new File(filename);
                    handleFile(file, encoding);
                }
            }
        
            private static void handleFile(File file, Charset encoding)
                    throws IOException {
                try (InputStream in = new FileInputStream(file);
                     Reader reader = new InputStreamReader(in, encoding);
                     // buffer for efficiency
                     Reader buffer = new BufferedReader(reader)) {
                    handleCharacters(buffer);
                }
            }
        
            private static void handleCharacters(Reader reader)
                    throws IOException {
                int r;
                while ((r = reader.read()) != -1) {
                    char ch = (char) r;
                    System.out.println("Do something with " + ch);
                }
            }
        }
        

        上述代码的坏处在于它使用了系统的默认字符集。尽可能选择已知的编码(如果可以选择,最好是 Unicode 编码)。有关更多信息,请参阅Charset 课程。 (如果你觉得自虐,可以阅读this guide to character encoding。)

        (您可能需要注意的一件事是补充 Unicode 字符 - 那些需要存储两个 char 值的字符。有关更多详细信息,请参阅Character 类;这是一个可能不会的边缘情况适用于家庭作业。)

        【讨论】:

        • 通常打开一个 FileInputStream 并将其包装在 InputStreamReader 中,指定字符编码。 (不幸的是,FileReader 不允许您指定编码。)
        • 我对此有疑问!如果我一次读取一个字符,为什么需要 BufferedReader?
        • @KareemMesbah 缓冲读取提高了性能,因为这意味着对read() 的大多数调用来自 RAM,而不是操作系统/磁盘。该代码将在没有缓冲区的情况下工作,或者您可以使用 BufferedInputStream 或通过调用 read(char[]) 来使用您自己的缓冲区。
        • 谢谢你——正是我一直在寻找的东西
        • @McDowell 与使用阅读器读取文件相比性能如何?
        【解决方案5】:

        在 java 5 中添加的新功能是 Scanner 方法,它可以在 java 中逐个字符地读取输入。

        例如; 使用 Scanner 方法 import java.util.Scanner; 在main方法之后:定义

        扫描仪 myScanner = new Scanner(System.in); //用于读取字符

        char 任何东西=myScanner.findInLine(".").charAt(0);

        您可以存储单个字符,如果您想要更多阅读更多字符,请声明更多对象,例如 any1,anything2... 您的答案的更多示例请检查您的手(复制/粘贴)

             import java.util.Scanner;
             class ReverseWord  {
        
            public static void main(String args[]){
            Scanner myScanner=new Scanner(System.in);
            char c1,c2,c3,c4;
        
            c1 = myScanner.findInLine(".").charAt(0);
                c2 = myScanner.findInLine(".").charAt(0);
            c3 = myScanner.findInLine(".").charAt(0);
            c4 = myScanner.findInLine(".").charAt(0);
        
            System.out.print(c4);
            System.out.print(c3);
            System.out.print(c2);
            System.out.print(c1);
            System.out.println();
        
           }
          }
        

        【讨论】:

          【解决方案6】:

          另一种选择是不逐个字符地读取内容——将整个文件读入内存。如果您需要多次查看字符,这很有用。一种简单的方法是:

            /** Read the contents of a file into a string buffer      */
              public static void readFile(File file, StringBuffer buf)
                  throws IOException
              {
              FileReader fr = null;
              try {
                fr = new FileReader(file);
                BufferedReader br = new BufferedReader(fr);
                char[] cbuf = new char[(int) file.length()];
                br.read(cbuf);  
                buf.append(cbuf);
                br.close();
              }
              finally {
                if (fr != null) {
                  fr.close();
                }
              }
          }
          

          【讨论】:

          • char[] 也可用于稍后搜索文件。 StringBuffer 仅用于将字符数组附加到 StringBuffer 并将其传递回执行的调用点。我想StringBuffer buf在进入方法时是空的。
          • 这是一个演示概念的示例方法。要实际使用该技术,我建议使用像 Guava 这样的库
          • 鉴于您已经在使用 BufferedReader,这实际上可能比设置标记和重置阅读器缓冲区要慢。在使用它之前获取性能指标是值得的。
          【解决方案7】:

          结合其他人关于指定字符编码和缓冲输入的建议,我认为这是一个非常完整的答案。

          假设你有一个File 对象代表你要读取的文件:

          BufferedReader reader = new BufferedReader(
              new InputStreamReader(
                  new FileInputStream(file),
                  Charset.forName("UTF-8")));
          int c;
          while((c = reader.read()) != -1) {
            char character = (char) c;
            // Do something with your character
          }
          

          【讨论】:

            【解决方案8】:

            将您的阅读器包裹在 BufferedReader 中,它会维护一个缓冲区,以便整体上更快地读取。然后,您可以使用 read() 读取单个字符(您需要转换)。您还可以使用 readLine() 获取整行,然后将其分成单个字符。 BufferedReader还支持标记和返回,所以如果需要,可以多次读取一行。

            一般来说,您希望使用 BufferedReader 或 BufferedInputStream 在您实际使用的任何流之上,因为它们维护的缓冲区将使多次读取更快。

            【讨论】:

              【解决方案9】:

              如果您使用BufferedReader,您有多种选择。这个缓冲的阅读器比阅读器快,所以你可以包装它。

              BufferedReader reader = new BufferedReader(new FileReader(path));
              reader.read(char[] buffer);
              

              这会将行读入 char 数组。你有类似的选择。查看文档。

              【讨论】:

                猜你喜欢
                • 2013-10-20
                • 1970-01-01
                • 1970-01-01
                • 2021-06-18
                • 2019-06-26
                • 1970-01-01
                • 2012-08-27
                • 2021-07-20
                • 1970-01-01
                相关资源
                最近更新 更多