-
Notifications
You must be signed in to change notification settings - Fork 0
/
Split-Csv.ps1
105 lines (89 loc) · 3.32 KB
/
Split-Csv.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using namespace System.Text
using namespace System.IO
function Split-Csv {
[CmdletBinding(DefaultParameterSetName = 'ByChunks')]
param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[alias('FullName')]
[string] $Path,
[Parameter(Mandatory)]
[string] $DestinationFolder,
[Parameter(ParameterSetName = 'BySize')]
[int64] $Size = 1kb,
[Parameter(ParameterSetName = 'ByChunks')]
[int32] $Chunks = 3,
[Parameter()]
[EncodingTransformation()]
[ArgumentCompleter([EncodingCompleter])]
[Encoding] $Encoding = 'utf8',
[Parameter()]
[switch] $PassThru
)
begin {
$Destination = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($DestinationFolder)
class ChunkWriter {
[FileInfo] $Source
[string] $Destination
[string] $Headers
[string] $Format
[Encoding] $Encoding
[StreamWriter] GetNewWriter([int32] $Index) {
$name = [string]::Format(
'{0} - Part {1}{2}',
$this.Source.BaseName,
$Index.ToString($this.Format),
$this.Source.Extension
)
$newChunk = Join-Path $this.Destination -ChildPath $name
$writer = [StreamWriter]::new($newChunk, $false, $this.Encoding)
$writer.AutoFlush = $true
$writer.WriteLine($this.Headers)
return $writer
}
}
}
process {
try {
[FileInfo] $Path = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path)
$null = [Directory]::CreateDirectory($Destination)
$reader = [StreamReader]::new($Path.FullName, $Encoding, $true)
$headers = $reader.ReadLine()
$Index = 0
if($PSCmdlet.ParameterSetName -eq 'ByChunks') {
$chunkSize = ($Path.Length - $headers.Length) / $Chunks + ($headers.Length * $Chunks)
$format = 'D{0}' -f $Chunks.ToString().Length
}
else {
$chunkSize = $Size - $headers.Length
$format = 'D{0}' -f [math]::Ceiling($Path.Length / $Size).ToString().Length
}
$chunkWriter = [ChunkWriter]@{
Source = $Path
Destination = $Destination
Headers = $headers
Format = $format
Encoding = $Encoding
}
$writer = $chunkWriter.GetNewWriter($Index++)
while(-not $reader.EndOfStream) {
if($writer.BaseStream.Length -ge $chunkSize) {
$writer.Dispose()
if($PassThru.IsPresent) {
$writer.BaseStream.Name -as [FileInfo]
}
$writer = $chunkWriter.GetNewWriter($Index++)
}
$writer.WriteLine($reader.ReadLine())
}
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
finally {
$writer, $reader | ForEach-Object Dispose
if($PassThru.IsPresent) {
$writer.BaseStream.Name -as [FileInfo]
}
}
}
}