IO 101: Каковы основные различия между TextWriter, FileStream и StreamWriter? - PullRequest
39 голосов
/ 18 июня 2009

Позвольте мне сначала извиниться, если этот вопрос может показаться, возможно, любительским для опытных программистов среди вас, дело в том, что у меня было много споров по этому поводу на работе, поэтому я действительно хочу понять это, и именно поэтому я полагаюсь на сообщество stackoverflow, чтобы решить эту проблему раз и навсегда:)

Итак, с одной стороны, согласно MSDN, имеем:

Класс TextWriter

Представляет писателя, который может написать последовательная серия символов. это класс абстрактный.

FileStream Class

Выставляет поток вокруг файла, поддерживая как синхронный, так и асинхронное чтение и запись операции.

Класс StreamWriter

Реализует TextWriter для записи символы в поток в определенном кодирование.

С другой стороны, очевидно, что все они принадлежат System.IO, но, учитывая, что примеры MSDN как-то смешивают некоторые из них, я все еще не достиг желаемого момента а-ха.

Любой комментарий будет более чем признателен, большое спасибо заранее!

Ответы [ 5 ]

57 голосов
/ 18 июня 2009

дескриптор потоков байтов , дескриптор Writers символов .

Байт! = Символы. Символ может занять более одного байта для представления. Отображение символов в байты называется кодированием .

A FileStream обозначает байты, записываемые в файл, аналогично тому, как MemoryStream обозначает байты, записываемые в буфер в памяти. Чтобы записывать символы в поток, вам необходимо преобразовать их в строку байтов. Вот тут и начинает играть StreamWriter. Он принимает последовательность символов и кодировку и превращает ее в последовательность байтов.

A TextWriter - это интерфейс (ну, абстрактный базовый класс), которого должны придерживаться все авторы. Все операции основаны на символах. Эквивалентом для байтов является Stream абстрактный базовый класс.

Вещи также идут в противоположном направлении. Существует TextReader абстрактный базовый класс, описывающий, как читать символы откуда-то, и StreamReader, который позволяет вам читать символы из байтово-ориентированного потока, предоставляющего кодировку - но на этот раз, наоборот, для агрегирования любых при необходимости, многобайтовые последовательности в одиночные символы.

A Stream может использоваться как для чтения, так и для записи, поскольку байты являются элементами самого низкого уровня, используемыми в операциях ввода / вывода.

10 голосов
/ 18 июня 2009

Я всегда находил лучшее, что можно сделать, это просто посмотреть, какие методы они предоставляют и как вы можете их построить. Это почти всегда главное, если не единственное, что меня волнует при использовании API. Как мне его построить и что он может сделать?

Вы не можете создать экземпляр TextWriter. Это абстрактно. Это говорит мне, что единственная реальная цель, которой он служит, это, ну, абстракция Если вы пишете функцию, которая принимает в качестве аргумента любой писатель, есть большая вероятность, что вы просто должны использовать TextWriter для большей универсальности.

StreamWriter, который вы можете создать, и он делает то, что говорит, пишет в потоки. Это означает, что для выполнения любой реальной записи потребуется поток. Однако, получив этот поток, вы можете делать все изящные вещи, например писать целую строку за раз, вместо того, чтобы иметь дело с отдельными символами (или, скорее, байтами), как если бы вы были непосредственно в потоке.

Таким образом, в основном вы получаете поток, чтобы вы могли передавать его в StreamWriter (или Reader). Если вы пишете текст, вы, вероятно, не хотите работать непосредственно с потоком, не больше, чем вы хотите работать с массивом символов вместо строки.

FileStreams может быть удобно создан непосредственно из классов File и FileInfo, и в моем случае именно так они обычно создаются. Получить файл (мне нравится использовать FileInfo) и вызвать OpenWrite (). Передайте его StreamWriter (это просто тип TextWriter), и вы уже в пути.

Обобщение: если вы хотите выяснить класс, попробуйте посмотреть, как вы его создаете, и что он может делать. Это обычно многое проясняет.

6 голосов
/ 18 июня 2009

Существует очевидная разница между «потоком» и «записывающим / считывающим устройством».

Поток - это представление уровня байтов, и оно действительно является абстрактной концепцией, которая может быть реализована различными способами.Например, у вас есть FileStream и MemoryStream.Оба являются потоками байтов, но они хранятся по-разному.

Устройства записи и чтения дают вам возможность обрабатывать потоки, добавлять и извлекать из них данные.

Для ваших конкретных примеров TextWriterабстрактный класс, который записывает символы в поток последовательно.Он имеет несколько реализаций (StreamWriter, StringWriter), которые полезны в разных контекстах.Вы бы использовали то, что имеет смысл в то время.Однако для нескольких API все, что нужно, это TextWriter, или что-то, чтобы вызывать «Write» или «WriteLine».Эти API не имеют значения, если ваш писатель используется для помещения чего-либо в строку, некоторую произвольную память или файл.

4 голосов
/ 18 июня 2009

Класс FileStream управляет получением дескриптора файла и открытием его для чтения или записи и других функций файловой системы. BinaryWriter записывает двоичные данные в поток, а StreamWriter записывает символьные данные в поток. Они оба могут использовать объект FileStream для записи двоичных или символьных данных в файлы.

TextWriter - это базовый класс, от которого наследуется StreamWriter. TextWriter предназначен для получения типа и вывода строки с использованием метода Write . Реализация метода TextWriter.Write в StreamWriter записывает строку или символьные данные в поток. BinaryWriter не наследует TextWriter, поскольку не записывает символьные данные в поток.

2 голосов
/ 14 июня 2018

Stream - абстрактный базовый класс, представляющий серию байтов.

  • MemoryStream - это поток байтов, хранящихся в памяти, подкрепленный массивом.

  • FileStream - это поток байтов в файле, обычно поддерживаемый дескриптором файла где-то на диске.

Текстовые символы сами состоят из байтов, и один символ может состоять из нескольких байтов, в зависимости от кодировки. Существуют некоторые стандартные классы, которые читают и пишут текст в разные источники с использованием определенной кодировки.

TextWriter - это абстрактный базовый класс для записи текстовых символов в пункт назначения.

  • StreamWriter записывает текстовые символы (в байтах) в поток байтов.
  • StringWriter записывает текстовые символы в строку (через StringBuilder).

TextReader - абстрактный базовый класс для чтения текстовых символов из источника.

  • StreamReader читает текстовые символы (преобразованные из байтов) из потока байтов.
  • StringReader читает текстовые символы из строки.

Stream, TextWriter, TextReader - все это абстрактные базовые классы, поэтому они никогда не используются напрямую, а через реализацию, подобную описанной выше. Однако вы увидите базовые классы в определениях методов, чтобы можно было использовать разные реализации, включая ваши собственные, если это необходимо. Абстрактные классы похожи на интерфейсы, но на самом деле могут определять логику для методов, которые могут быть повторно использованы без повторения одного и того же базового кода в каждой реализации.

...