Что нового

[Данные, строки] Чтение файла в 2d массив, ("пустой" последний элемент строки)

inx

Знающий
Сообщения
43
Репутация
12
Сторонняя программа сохраняет таблицу в текстовый файл с разделителем - @TAB (табуляция)
(Строка заголовков всегда одинаковая, из нее можно получить кол-во "столбцов")
Но строки, последний элемент которых "пустой" она сохраняет как:
данные01@TABданные02
(пример: bad_file.txt)
что не нравится скрипту чтения файла в 2d массив, он требует такое:
данные01@TABданные02@TAB
(пример: good_file.txt)
(Возможен даже вариант с двумя "пустыми" данные01@TAB@TAB, в "плохом" файле никакой табуляции два раза в конце не будет)


Как побороть проблему?

Код:
#include-Once
#include <File.au3>
#include <Array.au3>

$file = @ScriptDir & "\bad_file.txt"
;~ $file = @ScriptDir & "\good_file.txt"
Global $2DArray
Global $delim = @TAB
_FileToArray2D($file, $2DArray, $delim)
_ArrayDisplay($2DArray)

Func _FileToArray2D($aFile, ByRef $aArray, $aDelim, $aStartRow = 1, $aEndRow = 0)
Local $aRead, $aRows, $aColums, $aString
$aRead = FileOpen($aFile)
If $aStartRow < 1 Then $aStartRow = 1
$aRows = _FileCountLines($aFile) + 1 - $aStartRow
If $aEndRow >0 Then $aRows = $aRows - ($aRows - $aEndRow + $aStartRow -1)
If $aEndRow <0 Then $aRows = $aRows - ($aRows + $aEndRow)

$aColums = UBound(StringSplit(FileReadLine($aRead, $aStartRow), $aDelim))-1

FileSetPos($aRead, 0, $FILE_BEGIN)
FileReadLine($aRead,-1 + $aStartRow)

Local $aArrayTemp[$aRows + 1][$aColums]
$aArrayTemp[0][0] = $aRows

For $i = 1 to $aRows
$aString = StringSplit(FileReadLine($aRead), $aDelim)
For $k = 0 to $aColums -1
	  $aArrayTemp[$i][$k] = $aString[$k+1]
Next
Next

FileClose($aRead)
$aArray = $aArrayTemp
EndFunc


Может быть прочитать файл в одномерный масив,
подсчитать количество элементов в строке заголовков,
обработать каждую следующую строку на предмет добавления @TAB в конец, если в ней количество элементов будет меньше?
А потом уже переводить в 2d? (понятия не имею как это скажется на скорости)
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
inx,
Можно так попробовать.
Код:
#include <Array.au3>

Local $aTxt, $iUb2, $aRet[1], $aTmp, $aFile[2] = ['good_file.txt', 'bad_file.txt'], $iRand = Random(0, 1, 1), $iTimer = TimerInit(), $sHeader

$aTxt = StringSplit(StringStripCR(StringRegExpReplace(FileRead(@ScriptDir & '\' & $aFile[$iRand]), '[\r\n]*$', '')), @LF)
StringReplace(StringRegExpReplace($aTxt[1], '[\t]*$', ''), @TAB, '')
$iUb2 = @extended + 1
ReDim $aRet[$aTxt[0] + 1][$iUb2]
$aRet[0][0] = $aTxt[0]
For $i = 1 To $aTxt[0]
	$aTmp = StringSplit(StringRegExpReplace($aTxt[$i], '[\t]*$', ''), @TAB)
	For $j = 1 To $aTmp[0]
		$aRet[$i][$j - 1] = $aTmp[$j]
	Next
Next
$sHeader = $aFile[$iRand] & ' - ' & Round(TimerDiff($iTimer), 2) & ' ms'
_ArrayDisplay($aRet, $sHeader)
 

firex

AutoIT Гуру
Сообщения
943
Репутация
205
inx
Элементарно:

Код:
#include <File.au3>
#include <Array.au3>

Local Const $sFilePath = @ScriptDir & "\bad_file.txt", $sDelim = @TAB
Local $a2D ;This is empty array

_FileToArray2D( $a2D, $sFilePath, $sDelim )
_ArrayDisplay( $a2D )

Func _FileToArray2D( ByRef $a2D, $sFilePath, $sDelim )
	Local $vRead, $iCount, $aTmp, $Idx, $Jix
	; ---
	$vRead = StringRegExpReplace( FileRead( $sFilePath ), "[\r\n]+$", "" )
	If Not $vRead Then _
		Return SetError( 1 )

	$vRead = StringSplit( StringStripCR( $vRead ), @LF )
	If $vRead[0] < 2 Then _
		Return SetError( 2 )
	; ---
	StringRegExpReplace( $vRead[1], "\t", "" )
	$iCount = @Extended + 1

	Dim $a2D[$vRead[0]][$iCount] = [ [ $vRead[0]-1 ] ]
	For $Idx = 2 To $vRead[0] Step 1
		$aTmp = StringSplit( $vRead[$Idx], @TAB )
		For $Jix = 0 To $iCount - 1 Step 1
			If $aTmp[0] > $Jix Then
				$a2D[$Idx-1][$Jix] = $aTmp[$Jix+1]
			Else
				$a2D[$Idx-1][$Jix] = "" ;Элемент для которого нет значения, можете вписать свое.
			EndIf
		Next
	Next
EndFunc
 
Верх