如何将字符串写入OutputStream

12

如何创建一个类,该类需要一个OutputStream的实现,并将内容写入它?

例如,下面的打印方法是错误的,无法编译。有什么选项或更好的技术吗?

public class FooBarPrinter{
    private OutputStream o;
    public FooBarPrinter(OutputStream o){
        this.o=o;
    }

    public void print(String s){        
        o.write(s);
    }
}

6
您应该 1)查看 OutputStream API,并使用其可用的方法,2)如果遇到错误,请在此处发布错误信息,以便我们不必猜测出错的原因。 - Hovercraft Full Of Eels
4
例如,API会告诉你没有名为write(...)且带有String参数的OutputStream方法,因此你不能随意创建这样一个方法并期望它能正常工作。相反,你必须使用现有的可用方法。 - Hovercraft Full Of Eels
3个回答

23

通用的OutputStream无法直接将String写入其中。相反,您需要获取Stringbyte[],然后将它们写入流中。

public void print(String s){ 
    o.write(s.getBytes());
}

请参考OutputStream的Java文档,了解所支持的写入数据类型。

我建议您在构造函数中提供的OutputStreamBufferedOutputStream,这将提高代码的性能。它通过在内存中缓冲一些数据,并将其以大块而不是许多较小的写操作写入磁盘来工作。

这里是BufferedOutputStream的Java文档。


9
我认为其他答案忽略了一个重要的问题。你真的应该使用OutputStream吗?
OutputStream和InputStream类层次结构用于写入和读取面向字节的数据。但Java字符串不是面向字节的,它们是面向字符(初步估计),在Java中,字符是16位Unicode代码单元。
当您将字符写入字节流时,JVM必须进行转换以将字符编码为字节。实际上,有许多可能的方法来做到这一点。例如,UTF-8会将每个字符序列编码为一个或多个字节,Latin-1或ASCII将编码一部分字符作为单个字节并将其他字符转换为(可能是)问号。等等。
现在,您可以编写如下内容:
  public void print(String s){ 
      o.write(s.getBytes());
  }

但是它存在一个问题。问题在于String上的getBytes()方法使用JVM的默认字符编码方案进行转换。而这个(默认编码方案)取决于启动JVM的环境。因此,该代码会根据不同的环境执行不同的操作。现在,您可以通过指定字符集来解决这个问题:

  public void print(String s){ 
      o.write(s.getBytes("UTF-8"));
  }

但如果您在许多地方调用 getBytes,那将变得繁琐。

如果您需要大量基于文本的输出,更好的选择是使用 Writer API 而不是 OutputStream API。 Writer API 及其实现在幕后处理转换...并更加一致和高效。

最后一点是,还有其他 API 可以帮助进行基于文本的输出。

  • BufferedWriter 类(以及 BufferedOutputStream)通过将内存缓冲引入输出过程来支持有效输出。这可以节省系统调用,特别是当您执行大量小型写操作时。
  • PrintWriter 类提供了许多便捷方法,并且消除了处理 IOExceptions 的需要。(如果发生 IOException,则 PrintWriter 会做出备注。有一种方法可以测试是否发生异常。这可能有用或危险,具体取决于您正在做什么...)

2
要输出字符串,可以查看 PrintStream 类。你可以在 这里 看到一个实现你意图的类的示例。
此外,你可以使用 PrintStream 构造函数之一 来包装一个 OutputStream
public class FooBarPrinter{
  private PrintStream p;
  public FooBarPrinter(OutputStream o){
    p = new PrintStream(o);
  }
  public void print(String s){      
    p.print(s);
  }
}

编辑: 注意您也可以像上面的PrintStream一样使用PrintWriter类,这通常更好,因为您可以指定要使用的编码,避免任何平台依赖性。


3
需要注意的是,PrintStream 处理异常的方式不同于其他输出流:“与其他输出流不同,PrintStream 永远不会抛出 IOException 异常;相反,异常情况只会设置一个内部标志,可以通过 checkError() 方法进行测试。” - Greg Kopff
@GregKopff:是的,现在已经注意到了。谢谢! - Jordão

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接