【问题标题】:Getting meaningful text from Java.io.Reader从 Java.io.Reader 获取有意义的文本
【发布时间】:2012-01-30 19:41:57
【问题描述】:

我正在编写一个程序,我正在使用另一家公司的库从他们的网站下载一些报告。我想在将它们写入文件之前解析这些报告,因为如果它们符合某些条件,我想忽略它们。

问题是,他们的方法称为 download() 返回一个 java.io.Reader。我唯一可用的方法是

int read(char[] cbuf);

打印这个返回的数组给了我无意义的字符。我希望能够识别我正在使用的字符集或将其转换为字节数组,但我不知道该怎么做。我试过了

//retrievedFile is my Reader object
char[] cbuf = new char[2048];
int numChars = retrievedFile.read(cbuf);
//I've tried other character sets, too
new String(cbuf).getBytes("UTF-8");

而且我不敢向更有用的读者投降,因为我无法确定它是否有效。有什么建议吗?

编辑

当我说它打印出“无意义的字符”时,我并不是说它看起来像 Jon Skeet 给出的示例。这真的很难描述,因为我现在不在我的机器上,但我认为这是一个编码问题。这些字符似乎具有与报告外观相似的凹痕和结构。我会在星期二回来后尽快尝试这些建议(我只是一名实习生,所以我没有费心设置远程帐户或其他任何东西)。

【问题讨论】:

  • 你试过BufferedReader吗?它没有理由不工作......
  • 如果System.out.print(cbuf[i])给你i=0,1,2..的垃圾,那是对方公司的lib有问题,或者你没有配置好。

标签: java java-io


【解决方案1】:

将它包装在更有用的东西中,例如 StringReader 或 BufferedReader:

http://docs.oracle.com/javase/6/docs/api/

.

【讨论】:

    【解决方案2】:

    由于该文件是一个文本文件,因此从您的 Reader 创建一个 BufferedReader 并逐行阅读 - 这应该有助于理解它。

    【讨论】:

      【解决方案3】:

      它给出了什么无意义的字符。可能是 null 字符,因为您不会从 reader 读取所有字符,但最多读取 2048 个字符,并且您忽略 read 方法的返回值(它告诉您实际读取了多少个字符。

      如果要将整个内容读入字符串,则必须循环直到返回值为负数,并将每次迭代读取的字符(从 0 到 numChars)附加到 StringBuilder。

      StringBuilder builder = new StringBuilder();
      int numChars;
      while ((numChars = reader.read(cbuf)) >= 0) {
          builder.append(cbuf, 0, numChars);
      }
      String s = builder.toString();
      

      【讨论】:

      • 示例缺少cbuf 数组的定义。这是 IMO 最有效的解决方案。
      【解决方案4】:

      打印出char[] 本身可能会给你类似的东西:

      [C@1c8825a5
      

      这只是在 Java 中对 char 数组调用 toString 的正常输出。听起来您想将其转换为String,您可以使用String(char[]) 构造函数来完成。下面是一些示例代码:

      public class Test {
          public static void main(String[] args) {
              char[] chars = "hello".toCharArray();
              System.out.println((Object) chars);
      
              String text = new String(chars);
              System.out.println(text);
          }
      }
      

      另一方面,java.io.Reader 没有有一个 read 方法 返回一个 char[] - 它有返回单个字符的方法一个时间,或者(更有用)accept一个char[] 来填充数据,并返回读取的数据量。这实际上是您的示例代码显示的内容。您只需要使用 char 数组和读取的字符数来创建新的String。例如:

      char[] buffer = new char[4096];
      int charsRead = reader.read(buffer);
      String text = new String(buffer, 0, charsRead);
      

      但是,请注意,它可能不会一次性返回所有数据。您可以使用BufferedReader 逐行阅读,或者循环获取所有信息。 Guava 在其 CharStreams 类中包含有用的代码。例如:

      String allText = CharStreams.toString(reader);
      

      List<String> lines = CharStreams.readLines(reader);
      

      【讨论】:

      • 乔恩,我对方法的错误,我忘了它返回一个 int 并接受一个 char[]。打印出 char 数组看起来像是一个编码问题。甚至可能是公司搞砸了他们的实施,或者我配置错了,@amadeus 的帖子
      • @Tom:如果是编码问题,那可能只是因为实现搞砸了——如果给你一个Reader,你就不需要处理编码完全。你能提供图书馆的任何细节吗?
      【解决方案5】:

      试试这个:

      BufferedReader in = new BufferedReader(retrievedFile);
      String line = null;
      StringBuilder rslt = new StringBuilder();
      while ((line = in.readLine()) != null) {
          rslt.append(line);
      }
      System.out.println(rslt.toString());
      

      不要将 Reader 类型转换为任何类,因为您不知道它的真实类型。 相反,使用 BufferedReader 并将 Reader 传递给它。并且 BufferedReader 将 java.io.Reader 的任何子类作为参数,因此可以保存使用它。

      【讨论】:

      • 在我的场景中完美运行。
      • 这个实现是错误的!! BufferedReader 中的任何行终止符都将丢失,因为 BufferedReader.readLine 不包含行终止符!
      【解决方案6】:

      作为替代方案,您可以使用 java.util.Scannerjava.io.Reader 中读取字符串,并使用 try 和应自动关闭阅读器的资源。

      这是一个例子:

      Reader in = ...
      try (Scanner scanner = new Scanner(in).useDelimiter("\\Z")) {
          String text = scanner.next();
          ... // Do something with text
      }
      

      在这种情况下,对scanner.next() 的调用将读取所有字符,因为分隔符是文件的结尾。

      下面一行也会读完全文,但不会关闭阅读器:

      String text = new Scanner(in).useDelimiter("\\Z").next();
      

      【讨论】:

        猜你喜欢
        • 2011-04-27
        • 2014-05-15
        • 1970-01-01
        • 1970-01-01
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多