1 #Region "Microsoft.VisualBasic::0b6714930826e413b5320efe5892ef2d, Microsoft.VisualBasic.Core\Extensions\IO\Extensions\IO.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     Module IOExtensions
35     
36     '     Function: FixPath, FlushAllLines, (+3 Overloads) FlushStream, Open, OpenReader
37     '               OpenTextWriter, ReadBinary, ReadVector
38     
39     '     Sub: ClearFileBytes, FlushTo
40     
41     ' /********************************************************************************/
42
43 #End Region
44
45 Imports System.IO
46 Imports System.Runtime.CompilerServices
47 Imports System.Text
48 Imports Microsoft.VisualBasic.CommandLine.Reflection
49 Imports Microsoft.VisualBasic.FileIO
50 Imports Microsoft.VisualBasic.Language.Default
51 Imports Microsoft.VisualBasic.Linq
52 Imports Microsoft.VisualBasic.Scripting.MetaData
53 Imports Microsoft.VisualBasic.Text
54
55 ''' <summary>
56 ''' The extension API for system file io.(IO函数拓展)
57 ''' </summary>
58 <Package("IO")>
59 Public Module IOExtensions
60
61     ReadOnly UTF8 As DefaultValue(Of Encoding) = Encoding.UTF8
62
63     ''' <summary>
64     ''' Open text writer interface from a given <see cref="Stream"/> <paramref name="s"/>. 
65     ''' </summary>
66     ''' <param name="s"></param>
67     ''' <param name="encoding">By default is using <see cref="UTF8"/> text encoding.</param>
68     ''' <returns></returns>
69     <MethodImpl(MethodImplOptions.AggressiveInlining)>
70     <Extension>
71     Public Function OpenTextWriter(s As Stream, Optional encoding As Encoding = NothingAs StreamWriter
72         Return New StreamWriter(s, encoding Or UTF8) With {
73             .NewLine = ASCII.LF
74         }
75     End Function
76
77     ''' <summary>
78     ''' 
79     ''' </summary>
80     ''' <param name="stream">
81     ''' 必须要能够支持<see cref="Stream.Length"/>,对于有些网络服务器的HttpResponseStream可能不支持
82     ''' <see cref="Stream.Length"/>的话,这个函数将会报错
83     ''' </param>
84     ''' <param name="path$"></param>
85     ''' <returns></returns>
86     <MethodImpl(MethodImplOptions.AggressiveInlining)>
87     <Extension>
88     Public Function FlushStream(stream As Stream, path$) As Boolean
89         Dim buffer As Byte() = New Byte(stream.Length - 1) {}
90         Call stream.Read(buffer, Scan0, stream.Length)
91         Return buffer.FlushStream(path)
92     End Function
93
94     ''' <summary>
95     ''' 将指定的字符串的数据值写入到目标可写的输出流之中
96     ''' </summary>
97     ''' <param name="data$">所需要写入的字符串数据</param>
98     ''' <param name="out">输出流</param>
99     ''' 
100     <MethodImpl(MethodImplOptions.AggressiveInlining)>
101     <Extension>
102     Public Sub FlushTo(data$, out As StreamWriter)
103         Call out.WriteLine(data)
104     End Sub
105
106     ''' <summary>
107     ''' 为了方便在linux上面使用,这里会处理一下file://这种情况,请注意参数是ByRef引用的
108     ''' </summary>
109     ''' <param name="path$"></param>
110     ''' <returns></returns>
111     ''' 
112     <Extension> Public Function FixPath(ByRef path$) As String
113         If InStr(path, "file://", CompareMethod.Text) = 1 Then
114             If App.IsMicrosoftPlatform AndAlso InStr(path, "file:///", CompareMethod.Text) = 1 Then
115                 path = Mid(path, 9)
116             Else
117                 path = Mid(path, 8)
118             End If
119         Else
120             path = FileIO.FileSystem.GetFileInfo(path).FullName
121         End If
122
123         Return path$
124     End Function
125
126     ''' <summary>
127     ''' Read target text file as a numeric vector, each line in the target text file should be a number, 
128     ''' so that if the target text file have n lines, then the returned vector have n elements.
129     ''' (这个文本文件之中的每一行都是一个数字,所以假设这个文本文件有n行,那么所返回的向量的长度就是n)
130     ''' </summary>
131     ''' <param name="path">The file path of the target text file.</param>
132     ''' <returns></returns>
133     ''' 
134     <MethodImpl(MethodImplOptions.AggressiveInlining)>
135     <Extension>
136     Public Function ReadVector(path As StringAs Double()
137         Return File.ReadAllLines(path) _
138             .Select(Function(x) CDbl(x)) _
139             .ToArray
140     End Function
141
142     ''' <summary>
143     ''' Safe open a local file handle.
144     ''' (打开本地文件指针,这是一个安全的函数,会自动创建不存在的文件夹。这个函数默认是写模式的)
145     ''' </summary>
146     ''' <param name="path">文件的路径</param>
147     ''' <param name="mode">File open mode, default is create a new file.(文件指针的打开模式)</param>
148     ''' <param name="doClear">
149     ''' By default is clear all of the data in source file.
150     ''' (写模式下默认将原来的文件数据清空)
151     ''' 是否将原来的文件之中的数据清空?默认是,否则将会以追加模式工作
152     ''' </param>
153     ''' <returns></returns>
154     <ExportAPI("Open.File")>
155     <Extension>
156     Public Function Open(path$, Optional mode As FileMode = FileMode.OpenOrCreate, Optional doClear As Boolean = TrueAs FileStream
157         With path.ParentPath
158             If Not .DirectoryExists Then
159                 Call .MkDIR()
160             End If
161         End With
162
163         If doClear Then
164             ' 在这里调用FlushStream函数的话会导致一个循环引用的问题
165             Call ClearFileBytes(path)
166         End If
167
168         Return File.Open(path, mode)
169     End Function
170
171     ''' <summary>
172     ''' 将文件之中的所有数据都清空
173     ''' </summary>
174     ''' <param name="path"></param>
175     Public Sub ClearFileBytes(path As String)
176         Call IO.File.WriteAllBytes(path, New Byte() {})
177     End Sub
178
179     ''' <summary>
180     ''' Open a text file and returns its file handle.
181     ''' </summary>
182     ''' <param name="path"></param>
183     ''' <param name="encoding">使用系统默认的编码方案</param>
184     ''' <returns></returns>
185     ''' 
186     <MethodImpl(MethodImplOptions.AggressiveInlining)>
187     <ExportAPI("Open.Reader")>
188     <Extension>
189     Public Function OpenReader(path$, Optional encoding As Encoding = NothingAs StreamReader
190         Return New StreamReader(IO.File.Open(path, FileMode.OpenOrCreate), encoding Or UTF8)
191     End Function
192
193     ''' <summary>
194     ''' <see cref="IO.File.ReadAllBytes"/>, if the file is not exists on the filesystem, then a empty array will be return.
195     ''' </summary>
196     ''' <param name="path"></param>
197     ''' <returns></returns>
198     <Extension>
199     Public Function ReadBinary(path As StringAs Byte()
200         If Not path.FileExists Then
201             Return {}
202         Else
203             Return File.ReadAllBytes(path)
204         End If
205     End Function
206
207     ''' <summary>
208     ''' Write all object into a text file by using its <see cref="Object.ToString"/> method.
209     ''' </summary>
210     ''' <typeparam name="T"></typeparam>
211     ''' <param name="data"></param>
212     ''' <param name="saveTo"></param>
213     ''' <param name="encoding"></param>
214     ''' <returns></returns>
215     ''' 
216     <MethodImpl(MethodImplOptions.AggressiveInlining)>
217     <Extension> Public Function FlushAllLines(Of T)(data As IEnumerable(Of T), saveTo$, Optional encoding As Encodings = Encodings.Default) As Boolean
218         Return data.FlushAllLines(saveTo, encoding.CodePage)
219     End Function
220
221     ''' <summary>
222     ''' Save the binary data into the filesystem.(保存二进制数据包值文件系统)
223     ''' </summary>
224     ''' <param name="buf">The binary bytes data of the target package's data.(目标二进制数据)</param>
225     ''' <param name="path">The saved file path of the target binary data chunk.(目标二进制数据包所要进行保存的文件名路径)</param>
226     ''' <returns></returns>
227     ''' <remarks></remarks>
228     '''
229     <ExportAPI("FlushStream")>
230     <Extension> Public Function FlushStream(buf As IEnumerable(Of Byte), <Parameter("Path.Save")> path$) As Boolean
231         Using write As New BinaryWriter(path.Open)
232             For Each b As Byte In buf
233                 Call write.Write(b)
234             Next
235         End Using
236
237         Return True
238     End Function
239
240     <ExportAPI("FlushStream")>
241     <Extension> Public Function FlushStream(stream As Net.Protocols.ISerializable, savePath$) As Boolean
242         Dim rawStream As Byte() = stream.Serialize
243         If rawStream Is Nothing Then
244             rawStream = New Byte() {}
245         End If
246         Return rawStream.FlushStream(savePath)
247     End Function
248 End Module