1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . IO ;
4+ using System . IO . Compression ;
5+ using System . Linq ;
6+ using System . Threading . Tasks ;
7+
8+ namespace discogs
9+ {
10+ public interface IExporter < T > : IDisposable
11+ where T : IExportToCsv , new ( )
12+ {
13+ Task ExportAsync ( T value ) ;
14+ Task CompleteExportAsync ( int finalCount ) ;
15+ }
16+
17+ public class CsvExporter < T > : IExporter < T >
18+ where T : IExportToCsv , new ( )
19+ {
20+ private const int BufferSize = 1024 * 1024 ;
21+ private readonly string _typeName ;
22+ private readonly Dictionary < string , ( string FilePath , StreamWriter FileStream ) > _csvStreams ;
23+ private bool disposedValue ;
24+
25+ public CsvExporter ( string outPutDirectory , bool compress = false , bool verbose = false )
26+ {
27+ _typeName = typeof ( T ) . Name . Split ( '.' ) [ ^ 1 ] ;
28+ _csvStreams = GetCsvFilesFor ( outPutDirectory , compress ) ;
29+ }
30+ public async Task CompleteExportAsync ( int finalCount )
31+ {
32+ var csvFileNames = string . Join ( "; " , _csvStreams . Select ( kvp => kvp . Value . FilePath ) ) ;
33+ // pbar.WriteLine("Parsing done. Writing streams.");
34+ foreach ( var kvp in _csvStreams )
35+ {
36+ await kvp . Value . FileStream . FlushAsync ( ) ;
37+ kvp . Value . FileStream . Close ( ) ;
38+ // await kvp.Value.FileStream.DisposeAsync();
39+ }
40+ Console . WriteLine ( $ "Found { finalCount : n0} { _typeName } s. Wrote them to { csvFileNames } .") ;
41+ }
42+
43+ public async Task ExportAsync ( T value )
44+ {
45+ IEnumerable < ( string StreamName , string [ ] Row ) > csvExports = value . ExportToCsv ( ) ;
46+ foreach ( var ( streamName , row ) in csvExports )
47+ {
48+ await _csvStreams [ streamName ] . FileStream . WriteLineAsync ( CsvExtensions . ToCsv ( row ) ) ;
49+ }
50+ }
51+
52+ private static Dictionary < string , ( string FilePath , StreamWriter FileStream ) > GetCsvFilesFor ( string outPutDirectory , bool compress )
53+ {
54+ var obj = new T ( ) ;
55+ IReadOnlyDictionary < string , string [ ] > files = obj . GetCsvExportScheme ( ) ;
56+ Dictionary < string , ( string FilePath , StreamWriter FileStream ) > csvFiles = files . ToDictionary (
57+ kvp => kvp . Key ,
58+ kvp =>
59+ {
60+ var extension = compress ? "csv.gz" : "csv" ;
61+ var csvFile = Path . Combine ( outPutDirectory , $ "{ kvp . Key } .{ extension } ") ;
62+ StreamWriter stream ;
63+ if ( compress )
64+ {
65+ var fs = File . Create ( csvFile , bufferSize : BufferSize ) ;
66+ var gzStream = new GZipStream ( fs , CompressionMode . Compress , leaveOpen : false ) ;
67+ stream = new StreamWriter ( gzStream , encoding : System . Text . Encoding . UTF8 ) ;
68+ }
69+ else
70+ {
71+ stream = new StreamWriter ( csvFile , append : false , encoding : System . Text . Encoding . UTF8 , bufferSize : BufferSize ) ;
72+ }
73+ stream . WriteLine ( CsvExtensions . ToCsv ( kvp . Value ) ) ;
74+ return ( csvFile , stream ) ;
75+ } ) ;
76+
77+ return csvFiles ;
78+ }
79+
80+ // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
81+ // ~CsvExporter()
82+ // {
83+ // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
84+ // Dispose(disposing: false);
85+ // }
86+
87+ public void Dispose ( )
88+ {
89+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
90+ Dispose ( disposing : true ) ;
91+ GC . SuppressFinalize ( this ) ;
92+ }
93+
94+ protected virtual void Dispose ( bool disposing )
95+ {
96+ if ( ! disposedValue )
97+ {
98+ if ( disposing )
99+ {
100+ // dispose managed state (managed objects)
101+ foreach ( var kvp in _csvStreams )
102+ {
103+ var ( _, stream ) = kvp . Value ;
104+ stream . Dispose ( ) ;
105+ }
106+ }
107+
108+ // TODO: free unmanaged resources (unmanaged objects) and override finalizer
109+ // TODO: set large fields to null
110+ disposedValue = true ;
111+ }
112+ }
113+ }
114+ }
0 commit comments