* Process a text stream line by line (for CSV, etc.) * This handles cases where lines span multiple chunks.
(
callback: (line: string, lineNumber: number) => Promise<void> | void,
options: {
skipFirst?: boolean; // Skip first line (e.g., for headers)
maxLines?: number; // Maximum number of lines to process (for sampling)
} = {}
)
| 101 | * This handles cases where lines span multiple chunks. |
| 102 | */ |
| 103 | async readLines( |
| 104 | callback: (line: string, lineNumber: number) => Promise<void> | void, |
| 105 | options: { |
| 106 | skipFirst?: boolean; // Skip first line (e.g., for headers) |
| 107 | maxLines?: number; // Maximum number of lines to process (for sampling) |
| 108 | } = {} |
| 109 | ): Promise<{ lineCount: number; bytesProcessed: number }> { |
| 110 | const { skipFirst = false, maxLines = Infinity } = options; |
| 111 | const textDecoder = new TextDecoder(); |
| 112 | let buffer = ''; |
| 113 | let lineCount = 0; |
| 114 | let processedLines = 0; |
| 115 | |
| 116 | try { |
| 117 | while (!this.aborted) { |
| 118 | const { done, value } = await this.reader.read(); |
| 119 | |
| 120 | if (done) { |
| 121 | // Process any remaining data in buffer |
| 122 | if (buffer.length > 0) { |
| 123 | lineCount++; |
| 124 | if (!skipFirst || lineCount > 1) { |
| 125 | processedLines++; |
| 126 | if (processedLines <= maxLines) { |
| 127 | await callback(buffer, lineCount); |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | break; |
| 132 | } |
| 133 | |
| 134 | this.bytesProcessed += value.length; |
| 135 | |
| 136 | // Decode chunk and add to buffer |
| 137 | const text = textDecoder.decode(value, { stream: true }); |
| 138 | buffer += text; |
| 139 | |
| 140 | // Process complete lines |
| 141 | let lineEndIndex; |
| 142 | while ((lineEndIndex = buffer.indexOf('\n')) !== -1 && processedLines < maxLines) { |
| 143 | const line = buffer.substring(0, lineEndIndex).trim(); |
| 144 | buffer = buffer.substring(lineEndIndex + 1); |
| 145 | |
| 146 | if (line.length > 0) { |
| 147 | lineCount++; |
| 148 | if (!skipFirst || lineCount > 1) { |
| 149 | processedLines++; |
| 150 | if (processedLines <= maxLines) { |
| 151 | await callback(line, lineCount); |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | if (processedLines >= maxLines) { |
| 157 | break; |
| 158 | } |
| 159 | } |
| 160 |
no test coverage detected