@@ -13,6 +13,7 @@ This Source Code Form is subject to the terms of the
1313using OneScript . Execution ;
1414using OneScript . Types ;
1515using OneScript . Values ;
16+ using OneScript . StandardLibrary . Binary ;
1617using ScriptEngine . Machine ;
1718using ScriptEngine . Machine . Contexts ;
1819
@@ -22,52 +23,75 @@ namespace OneScript.StandardLibrary.Text
2223 public class TextWriteImpl : AutoContext < TextWriteImpl > , IDisposable
2324 {
2425 StreamWriter _writer ;
26+ IStreamWrapper _streamWrapper ;
27+ Encoding _encoding ;
2528 string _lineDelimiter = "" ;
2629 string _eolReplacement = "" ;
2730
2831 public TextWriteImpl ( )
2932 {
3033
3134 }
32-
35+
3336 public TextWriteImpl ( string path , IValue encoding )
3437 {
35- Open ( path , encoding ) ;
38+ Open ( ValueFactory . Create ( path ) , encoding ) ;
3639 }
3740
3841 public TextWriteImpl ( string path , IValue encoding , bool append )
3942 {
40- Open ( path , encoding , null , append ) ;
43+ Open ( ValueFactory . Create ( path ) , encoding , null , ValueFactory . Create ( append ) ) ;
4144 }
4245
46+ public TextWriteImpl ( IValue stream , IValue encoding , IValue writeBom )
47+ {
48+ Open ( stream , encoding , null , null , writeBom ) ;
49+ }
50+
4351 /// <summary>
44- /// Открывает файл для записи.
52+ /// Открывает файл или устанавливает поток для записи.
4553 /// </summary>
46- /// <param name="path">Путь к файлу </param>
54+ /// <param name="fileOrStream">Имя файла или поток, в который будет выполнена запись. </param>
4755 /// <param name="encoding">Кодировка (необязательный). По умолчанию используется utf-8</param>
48- /// <param name="lineDelimiter">Разделитель строк (необязательный).</param>
49- /// <param name="append">Признак добавления в конец файла (необязательный)</param>
50- /// <param name="eolReplacement">Разделитель строк в файле (необязательный).</param>
56+ /// <param name="lineDelimiter">
57+ /// Определяет строку, разделяющую строки в файле/потоке (необязательный).
58+ /// Значение по умолчанию: ПС.</param>
59+ /// <param name="param4">
60+ /// Для файла:
61+ /// Признак добавления в конец файла (необязательный).
62+ /// Значение по умолчанию: Ложь.
63+ /// Для потока:
64+ /// Определяет разделение строк в потоке для конвертации в стандартный перевод строк ПС (необязательный).
65+ /// Значение по умолчанию: ВК + ПС.</param>
66+ /// <param name="param5">
67+ /// Для файла:
68+ /// Определяет разделение строк в файле для конвертации в стандартный перевод строк ПС (необязательный).
69+ /// Значение по умолчанию: ВК + ПС.
70+ /// Для потока:
71+ /// Если в начало потока требуется записать метку порядка байтов (BOM) для используемой кодировки текста,
72+ /// то данный параметр должен иметь значение Истина.
73+ /// Значение по умолчанию: Ложь.</param>
5174 [ ContextMethod ( "Открыть" , "Open" ) ]
52- public void Open ( string path , IValue encoding = null , string lineDelimiter = null , bool append = false , string eolReplacement = null )
75+ public void Open ( IValue fileOrStream , IValue encoding = null , string lineDelimiter = null , IValue param4 = null , IValue param5 = null )
5376 {
54- _lineDelimiter = lineDelimiter ?? "\n " ;
55- _eolReplacement = eolReplacement ?? "\r \n " ;
56-
57- Encoding enc ;
58- if ( encoding == null )
77+ if ( fileOrStream is IStreamWrapper streamWrapper )
5978 {
60- enc = new UTF8Encoding ( true ) ;
79+ OpenStream (
80+ streamWrapper ,
81+ encoding ,
82+ lineDelimiter ,
83+ ContextValuesMarshaller . ConvertValueStrict < string > ( param4 ) ,
84+ ContextValuesMarshaller . ConvertValueStrict < bool > ( param5 ) ) ;
6185 }
6286 else
6387 {
64- enc = TextEncodingEnum . GetEncoding ( encoding ) ;
65- if ( enc . WebName == "utf-8" && append == true )
66- enc = new UTF8Encoding ( false ) ;
88+ OpenFile (
89+ fileOrStream . ToString ( ) ,
90+ encoding ,
91+ lineDelimiter ,
92+ ContextValuesMarshaller . ConvertValueStrict < bool > ( param4 ) ,
93+ ContextValuesMarshaller . ConvertValueStrict < string > ( param5 ) ) ;
6794 }
68-
69- _writer = new StreamWriter ( path , append , enc ) ;
70- _writer . AutoFlush = true ;
7195 }
7296
7397 [ ContextMethod ( "Закрыть" , "Close" ) ]
@@ -83,8 +107,8 @@ public void Close()
83107 [ ContextMethod ( "Записать" , "Write" ) ]
84108 public void Write ( string what )
85109 {
86- ThrowIfNotOpened ( ) ;
87-
110+ PrepareForWriting ( ) ;
111+
88112 var stringToOutput = what . Replace ( "\n " , _eolReplacement ) ;
89113
90114 _writer . Write ( stringToOutput ) ;
@@ -98,58 +122,149 @@ public void Write(string what)
98122 [ ContextMethod ( "ЗаписатьСтроку" , "WriteLine" ) ]
99123 public void WriteLine ( IBslProcess process , string what , BslValue delimiter = null )
100124 {
101- ThrowIfNotOpened ( ) ;
102-
103- Write ( what ) ;
125+ Write ( what ) ;
104126
105127 var sDelimiter = _lineDelimiter ;
106128 if ( delimiter != null && delimiter . SystemType != BasicTypes . Undefined )
107129 sDelimiter = delimiter . ToString ( process ) ;
108130
109- Write ( sDelimiter ) ;
131+ Write ( sDelimiter ) ;
110132 }
111133
112134 public void ThrowIfNotOpened ( )
113135 {
114136 if ( _writer == null )
115137 throw new RuntimeException ( "Файл не открыт" ) ;
116- }
117-
138+ }
139+
118140 public void Dispose ( )
119141 {
120142 if ( _writer != null )
121143 {
122144 _writer . Dispose ( ) ;
123145 _writer = null ;
124146 }
147+
148+ _streamWrapper = null ;
149+ }
150+
151+ private void PrepareForWriting ( )
152+ {
153+ ThrowIfClosedStream ( ) ;
154+ ThrowIfNonWritableStream ( ) ;
155+
156+ if ( _writer == null && _streamWrapper != null )
157+ {
158+ _writer = new StreamWriter ( _streamWrapper . GetUnderlyingStream ( ) , _encoding , - 1 , true ) ;
159+ _writer . AutoFlush = true ;
160+ }
161+
162+ ThrowIfNotOpened ( ) ;
163+ }
164+
165+ private void OpenFile ( string path , IValue encoding = null , string lineDelimiter = null , bool append = false , string eolReplacement = null )
166+ {
167+ Dispose ( ) ;
168+
169+ _lineDelimiter = lineDelimiter ?? "\n " ;
170+ _eolReplacement = eolReplacement ?? "\r \n " ;
171+ _encoding = ResolveEncodingForFile ( encoding , append ) ;
172+ _streamWrapper = null ;
173+
174+ _writer = new StreamWriter ( path , append , _encoding ) ;
175+ _writer . AutoFlush = true ;
125176 }
126177
178+ private void OpenStream ( IStreamWrapper streamWrapper , IValue encoding = null , string lineDelimiter = null , string eolReplacement = null , bool writeBom = false )
179+ {
180+ Dispose ( ) ;
181+
182+ _lineDelimiter = lineDelimiter ?? "\n " ;
183+ _eolReplacement = eolReplacement ?? "\r \n " ;
184+ _encoding = ResolveEncodingForStream ( encoding , writeBom ) ;
185+ _streamWrapper = streamWrapper ;
186+ }
187+
188+ private Encoding ResolveEncodingForFile ( IValue encoding , bool append )
189+ {
190+ Encoding enc ;
191+ if ( encoding == null )
192+ {
193+ enc = new UTF8Encoding ( true ) ;
194+ }
195+ else
196+ {
197+ enc = TextEncodingEnum . GetEncoding ( encoding ) ;
198+ if ( enc . WebName == "utf-8" && append == true )
199+ enc = new UTF8Encoding ( false ) ;
200+ }
201+ return enc ;
202+ }
203+
204+ private Encoding ResolveEncodingForStream ( IValue encoding , bool writeBom )
205+ {
206+ if ( encoding == null )
207+ {
208+ return new UTF8Encoding ( writeBom ) ;
209+ }
210+ else
211+ {
212+ return TextEncodingEnum . GetEncoding ( encoding , writeBom ) ;
213+ }
214+ }
215+
216+ private void ThrowIfClosedStream ( )
217+ {
218+ if ( _streamWrapper != null )
219+ {
220+ var stream = _streamWrapper . GetUnderlyingStream ( ) ;
221+ if ( stream is { CanWrite : false , CanRead : false } )
222+ throw RuntimeException . ClosedStream ( ) ;
223+ }
224+ }
225+
226+ private void ThrowIfNonWritableStream ( )
227+ {
228+ if ( _streamWrapper != null && _streamWrapper . IsReadOnly )
229+ throw RuntimeException . NonWritableStream ( ) ;
230+ }
231+
127232 /// <summary>
128- /// Создает объект с начальными значениями имени файла и кодировки .
233+ /// Создает объект для записи текста в файл или поток .
129234 /// </summary>
130- /// <param name="path">Имя файла</param>
131- /// <param name="encoding">Кодировка в виде строки</param>
132- /// <param name="lineDelimiter">Символ - разделитель строк</param>
133- /// <param name="append">Признак добавления в конец файла (необязательный)</param>
134- /// <param name="eolReplacement">Разделитель строк в файле (необязательный).</param>
235+ /// <param name="fileOrStream">Имя файла или поток, в который будет выполнена запись.</param>
236+ /// <param name="encoding">Кодировка (необязательный). По умолчанию используется utf-8</param>
237+ /// <param name="lineDelimiter">
238+ /// Определяет строку, разделяющую строки в файле/потоке (необязательный).
239+ /// Значение по умолчанию: ПС.</param>
240+ /// <param name="param4">
241+ /// Для файла:
242+ /// Признак добавления в конец файла (необязательный).
243+ /// Значение по умолчанию: Ложь.
244+ /// Для потока:
245+ /// Определяет разделение строк в потоке для конвертации в стандартный перевод строк ПС (необязательный).
246+ /// Значение по умолчанию: ВК + ПС.</param>
247+ /// <param name="param5">
248+ /// Для файла:
249+ /// Определяет разделение строк в файле для конвертации в стандартный перевод строк ПС (необязательный).
250+ /// Значение по умолчанию: ВК + ПС.
251+ /// Для потока:
252+ /// Если в начало потока требуется записать метку порядка байтов (BOM) для используемой кодировки текста,
253+ /// то данный параметр должен иметь значение Истина.
254+ /// Значение по умолчанию: Ложь.</param>
135255 [ ScriptConstructor ( Name = "По имени файла" ) ]
136- public static TextWriteImpl Constructor ( string path , IValue encoding = null , string lineDelimiter = null , bool append = false , string eolReplacement = null )
256+ public static TextWriteImpl Constructor ( IValue fileOrStream , IValue encoding = null , string lineDelimiter = null , IValue param4 = null , IValue param5 = null )
137257 {
138258 var result = new TextWriteImpl ( ) ;
139-
140- string sLineDelimiter = lineDelimiter ?? "\n " ;
141- string sEolReplacement = eolReplacement ?? "\r \n " ;
142-
143- result . Open ( path , encoding , sLineDelimiter , append , sEolReplacement ) ;
144-
259+ result . Open ( fileOrStream , encoding , lineDelimiter , param4 , param5 ) ;
145260 return result ;
146261 }
147-
262+
148263 [ ScriptConstructor ( Name = "Формирование неинициализированного объекта" ) ]
149264 public static TextWriteImpl Constructor ( )
150265 {
151266 return new TextWriteImpl ( ) ;
152267 }
153268
154269 }
155- }
270+ }
0 commit comments