Modify

Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#2242 closed Bug (Fixed)

_FileWriteFromArray is incapable of writing only the zeroth element

Reported by: BrewManNH Owned by: guinness
Milestone: 3.3.9.5 Component: Standard UDFs
Version: 3.3.8.1 Severity: None
Keywords: Cc:

Description

In the File.au3 UDF, the function _FileWriteFromArray can't be used to write only the zeroth [0] of an array due to the way it is written. It has the capability to write any other single element, such as [1] or [2], but you can't output to a file the first element.

There is a simple fix for it, but it would be a script breaking change if applied.

; <<< default value for $I_Ubound changed to -1 instead of 0 >>>
Func _FileWriteFromArray($File, $a_Array, $i_Base = 0, $i_UBound = -1, $s_Delim = "|")
	; Check if we have a valid array as input
	If Not IsArray($a_Array) Then Return SetError(2, 0, 0)
	Local $iDims = UBound($a_Array, 0)
	If $iDims > 2 Then Return SetError(4, 0, 0)

	; determine last entry
	Local $last = UBound($a_Array) - 1
; <<< This line changed to look for the value of $i_Ubound < 0 instead of $i_Ubound < 1 >>>
	If $i_UBound < 0 Or $i_UBound > $last Then $i_UBound = $last
	If $i_Base < 0 Or $i_Base > $last Then $i_Base = 0

	; Open output file for overwrite by default, or use input file handle if passed
	Local $hFile
	If IsString($File) Then
		$hFile = FileOpen($File, $FO_OVERWRITE)
	Else
		$hFile = $File
	EndIf
	If $hFile = -1 Then Return SetError(1, 0, 0)

	; Write array data to file
	Local $ErrorSav = 0
	Switch $iDims
		Case 1
			For $x = $i_Base To $i_UBound
				If FileWrite($hFile, $a_Array[$x] & @CRLF) = 0 Then
					$ErrorSav = 3
					ExitLoop
				EndIf
			Next
		Case 2
			Local $s_Temp
			For $x = $i_Base To $i_UBound
				$s_Temp = $a_Array[$x][0]
				For $y = 1 To $iDims - 1
					$s_Temp &= $s_Delim & $a_Array[$x][$y]
				Next
				If FileWrite($hFile, $s_Temp & @CRLF) = 0 Then
					$ErrorSav = 3
					ExitLoop
				EndIf
			Next
	EndSwitch

	; Close file only if specified by a string path
	If IsString($File) Then FileClose($hFile)

	; Return results
	If $ErrorSav Then Return SetError($ErrorSav, 0, 0)
	Return 1
EndFunc   ;==>_FileWriteFromArray

It's only 2 values in 2 lines that need to be changed, but would result in it being a script breaking change due to this.

Attachments (0)

Change History (8)

comment:1 Changed 7 years ago by trancexx

That's why Default keyword should be used instead of magic numbers/strings.

comment:2 Changed 7 years ago by BrewManNH

I'd have to agree on that as well, if this had been written correctly in the first place, 0 would never have meant the whole array because AutoIt arrays are 0 based, and not 1 based. It should probably be rewritten to use the Default keyword in the $i_Ubound parameter, but at least the way it's written above would allow you to write out only the first element of the array.

comment:3 Changed 7 years ago by Valik

This is really stupid. I expected this function to be written by some stupid dumbass... but nope, it was written by somebody who should have known better.

Anyway, this function is dumb and broken. Please re-write it correctly. All I ask is that you do not modify the function signature. Chances are people who are writing the entire array aren't even specifying 0 explicitly so if it's changed to Default it will only affect a very small number of people who are writing the entire array using a non-default delimiter. Or idiots who wrote bad code but I don't care about them.

comment:4 Changed 7 years ago by BrewManNH

Here's what I came up with for a fix. I've also added in another error code because the original function would take a start index that is greater than the end index as a valid input, it would convert it to 0 in that case. I changed it to an error condition.

; #FUNCTION# ====================================================================================================================
; Name...........: _FileWriteFromArray
; Description ...: Writes Array records to the specified file.
; Syntax.........: _FileWriteFromArray($File, $a_Array[, $i_Base = 0[, $i_UBound = 0 [, $s_Delim= "|"]])
; Parameters ....: $File     - String path of the file to write to, or a file handle returned from FileOpen().
;                  $a_Array  - The array to be written to the file.
;                  $i_Base   - Optional: Start Array index to read, normally set to 0 or 1. Default=0
;                  $i_Ubound - Optional: Set to the last record you want to write to the File. default= whole array.
;                  $s_Delim  - Optional: Delimiter character(s) for 2-dimension arrays. default="|"
; Return values .: Success - Returns a 1
;                  Failure - Returns a 0
;                  @Error  - 0 = No error.
;                  |1 = Error opening specified file
;                  |2 = Input is not an Array
;                  |3 = Error writing to file
;                  |4 = Array dimensions > 2
;                  |5 = $i_Base > $i_UBound
; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
; Modified.......: Updated for file handles by PsaltyDS, @error = 4 msg and 2-dimension capability added by SPiff59
; Remarks .......: If a string path is provided, the file is overwritten and closed.
;                  To use other write modes, like append or Unicode formats, open the file with FileOpen() first and pass the file handle instead.
;                  If a file handle is passed, the file will still be open after writing.
; Related .......: _FileReadToArray
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _FileWriteFromArray($File, $a_Array, $i_Base = Default, $i_UBound = Default, $s_Delim = "|")
     ; Check if we have a valid array as input
     If Not IsArray($a_Array) Then Return SetError(2, 0, 0)
     Local $iDims = UBound($a_Array, 0)
     If $iDims > 2 Then Return SetError(4, 0, 0)
     ; determine last entry
     Local $last = UBound($a_Array) - 1
     If $i_UBound = Default Or $i_UBound > $last Then $i_UBound = $last
     ; determine last entry
     If $i_Base < 0 Or $i_Base = Default Then $i_Base = 0
     ; new error condition if $i_Base > than $i_UBound
     If $i_Base > $i_UBound Then Return SetError(5, 0, 0)
     ; Open output file for overwrite by default, or use input file handle if passed
     Local $hFile
     If IsString($File) Then
          $hFile = FileOpen($File, $FO_OVERWRITE)
     Else
          $hFile = $File
     EndIf
     If $hFile = -1 Then Return SetError(1, 0, 0)
     ; Write array data to file
     Local $ErrorSav = 0
     Switch $iDims
          Case 1
               For $x = $i_Base To $i_UBound
                    If FileWrite($hFile, $a_Array[$x] & @CRLF) = 0 Then
                         $ErrorSav = 3
                         ExitLoop
                    EndIf
               Next
          Case 2
               Local $s_Temp
               For $x = $i_Base To $i_UBound
                    $s_Temp = $a_Array[$x][0]
                    For $y = 1 To $iDims - 1
                         $s_Temp &= $s_Delim & $a_Array[$x][$y]
                    Next
                    If FileWrite($hFile, $s_Temp & @CRLF) = 0 Then
                         $ErrorSav = 3
                         ExitLoop
                    EndIf
               Next
     EndSwitch
     ; Close file only if specified by a string path
     If IsString($File) Then FileClose($hFile)
     ; Return results
     If $ErrorSav Then Return SetError($ErrorSav, 0, 0)
     Return 1
EndFunc   ;==>_FileWriteFromArray

comment:5 Changed 7 years ago by BrewManNH

I also came up with this as an alternative line

If $i_UBound = Default Or $i_UBound > $last Or $i_UBound < 0 Then $i_UBound = $last

This change would allow the use of -1 in the $i_UBound parameter to indicate the default parameter.

comment:6 Changed 7 years ago by trancexx

If you think or feel you need patronizer then maybe you shouldn't write that function.
I'm just saying. <-who says that? lol

comment:7 Changed 7 years ago by guinness

  • Milestone set to 3.3.9.5
  • Owner set to guinness
  • Resolution set to Fixed
  • Status changed from new to closed

Fixed by revision [7245] in version: 3.3.9.5

comment:8 Changed 7 years ago by guinness

The code above contains a bug that has been fixed in the latest beta when writing 2-dimensional arrays.

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as closed The owner will remain guinness.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.