Записать строку в выходной поток

140

У меня есть несколько слушателей вывода, которые реализуют OutputStream. Это может быть либо запись PrintStream в стандартный вывод или файл, либо запись в память или любое другое место назначения вывода; поэтому я указал OutputStream как () аргумент в методе.

Теперь я получил строку. Как лучше всего писать здесь в потоки?

Должен ли я просто использовать Writer.write (message.getBytes ())? Я могу передать ему байты, но если целевой поток является символьным, будет ли он преобразован автоматически?

Нужно ли мне вместо этого использовать мостовые потоки?

ярд
источник
2
Я не уверен, но это похоже на то, что вы пытаетесь здесь изобрести колесо, просматривали ли вы Java Base API, а также Commons IO API?
posdef 01

Ответы:

152

Потоки ( InputStreamи OutputStream) передают двоичные данные. Если вы хотите записать строку в поток, вы должны сначала преобразовать ее в байты или, другими словами, закодировать ее. Вы можете сделать это вручную (как вы предлагаете), используя String.getBytes(Charset)метод, но вам следует избегать этого String.getBytes()метода, поскольку он использует кодировку JVM по умолчанию, которую нельзя надежно предсказать переносимым способом.

Однако обычный способ записи символьных данных в поток - это заключить поток в объект Writer(часто a PrintWriter), который выполняет преобразование за вас, когда вы вызываете его write(String)(или print(String)) метод. Соответствующая оболочка для InputStreams - это Reader .

PrintStream- это особая OutputStreamреализация в том смысле, что она также содержит методы, которые автоматически кодируют строки (внутренне использует средство записи). Но это все же ручей. Вы можете безопасно обернуть свой поток писателем, независимо от того, является ли он PrintStreamреализацией потока или какой-либо другой. Нет опасности двойного кодирования.

Пример PrintWriter с OutputStream:

try (PrintWriter p = new PrintWriter(new FileOutputStream("output-text.txt", true))) {
    p.println("Hello");
} catch (FileNotFoundException e1) {
    e1.printStackTrace();
}
MForster
источник
4
Так что использование PrintWriterпохоже на использование String.getBytes(). Он использует любую случайную кодировку, которая является значением JVM по умолчанию. Так что это работает, только если вам повезет.
Christoffer Hammarström
108

OutputStream записывает байты, String предоставляет символы. Вам необходимо определить Charset для кодирования строки в byte []:

outputStream.write(string.getBytes(Charset.forName("UTF-8")));

Измените UTF-8кодировку по вашему выбору.

Петр Кнего
источник
3
Добавьте следующую строку. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Сахил Патель
.getBytes(StandardCharsets.UTF_8)немного чище
Sadap
32

Вы можете создать оболочку PrintStream вокруг OutputStream, а затем просто вызвать ее print (String):

final OutputStream os = new FileOutputStream("/tmp/out");
final PrintStream printStream = new PrintStream(os);
printStream.print("String");
printStream.close();
Илларион Ковальчук
источник
2
Какой набор символов использует PrintStream для преобразования в байты?
Дин Хиллер
21

По замыслу это делается так:

OutputStream out = ...;
try (Writer w = new OutputStreamWriter(out, "UTF-8")) {
    w.write("Hello, World!");
} // or w.close(); //close will auto-flush
Антонио
источник
3
Обратите внимание, что это w.close()тоже закроется out.
Франклин Ю
12

Оберните свой OutputStream в PrintWriter и используйте методы печати этого класса. Они принимают String и делают всю работу за вас.

НГ.
источник
9

Вы можете использовать Apache Commons IO :

try (OutputStream outputStream = ...) {
    IOUtils.write("data", outputStream, "UTF-8");
}
Феликс
источник
IOUtils.write(String data, OutputStream output, Charset encoding)реализован как output.write(data.getBytes(Charsets.toCharset(encoding))), поэтому может, если закодированная строка не помещается в массив байтов
Шарунас