fbpx
Welcome, Guest
Username: Password: Remember me
Visual Objects

Please use this forum to post questions about Visual Objects and Vulcan.NET
  • Page:
  • 1

TOPIC: Insert text at top of a file

Insert text at top of a file 2 months 3 weeks ago #1

Hello,

I am trying to add fields names to top of a CSV file. The issue is that the newly added line overwrites the first line in the passed text file. How to avoid the issue by moving first line down and inserting the new line.

BTW, I am using DBServer:CopyDelimited() to create the CSV file.
function AddFieldsHeaders(cFileName as string, cDelim as string, aListBoxItems as array) as void pascal 
	local ptrHandle as ptr 
	LOCAL I as DWORD      
	LOCAL dwFieldsCount := ALen(aListBoxItems) as DWORD     
	
	IF (ptrHandle := FOpen2(cFileName, FO_READWRITE)) != F_ERROR
   	 		 
		 // Reset file position to beginning-of-file
		
		 FSeek(ptrHandle, 0)
		 
		 FOR I := 1 upto dwFieldsCount
		 	  FWrite(ptrHandle,  cDelim + aListBoxItems[I] + cDelim + iif( I < dwFieldsCount, ",",""))
		 next

		 FWrite(ptrHandle, CRLF)
		 		 
		
		 FClose(ptrHandle)
		 		
		ENDIF

	return		

Any hints appreciated.

Happy New Year!
Jamal

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 3 weeks ago #2

Jamal,
There is no FInsert().

In VO and Vulcan with the F..() functions:
- Create a new file with a new name
- Write the header line
- Write the whole original file
- Close the new file
- Delete the original file
- Rename the new file to the original file.

or if you don't want to work with 2 files:
- Open the file Read/Write
- Read the whole buffer in a variable (string or allocated memory)
- FSeek() to begin of file
- Fwrite the header line
- Fwrite the copy of the buffer that you saved in the variable
- Close the file.

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 3 weeks ago #3

Robert,

I used the 2 files method and it worked fine.

Thanks!
Jamal

Edit:
I decided finally it's probably more efficient and faster to use only one file, so here is the code if anyone find it useful:
function AddFieldsHeaders(cFileName as string, cDelim as string, aListBoxItems as array) as void pascal 
        local cFileContents as string		
	local pInFile as ptr 
	LOCAL I as DWORD      
	LOCAL dwFieldsCount := ALen(aListBoxItems) as DWORD     

	cFileContents := LoadFileContents(cFileName)  // this calls a C# method.  MemoRead() can be used, but found it unreliable in some situations.
	
	IF (pInFile := FOpen2(cFileName, FO_READWRITE)) != F_ERROR    
		
		FOR I := 1 upto dwFieldsCount
			FWrite(pInFile,  cDelim + aListBoxItems[I] + cDelim + iif( I < dwFieldsCount, ",",_chr(13)))
		next     
		
		FWrite(pInFile, cFileContents) 
		 		
		FClose(pInFile) 
		  		
	ENDIF   
RETURN

Please Log in or Create an account to join the conversation.

Last edit: by Jamal.

Insert text at top of a file 2 months 3 weeks ago #4

Hi Robert and Chris,

Because Jamal has mentioned Memoread(), i´ve looked at what memoread() and memowrit() are currently doing.

i have a OEM textfile with this content:

Das ist ein Test
mit den Umlauten Ž™š„”
und auch mit á

The correctly converted content looks like:

Das ist ein Test
mit den Umlauten ÄÖÜäöü
und auch mit ß

1.) VO behaviour

According the VO-Help MemoRead() and MemWrit() make a automatic conversion, if setAnsi() is set to false.
While MemoWrit() respects the SetAnsi() setting, MemoRead() ignores it. So, reading the OEM-File
requires a Oem2Ansi() .
	SetAnsi ( FALSE )
	
	c := Oem2Ansi(MemoRead ( "D:\test\oemtest1.txt") )
 	
   
   // because setansi(.f.) is still active , oemtest2.txt 
  // has the same Oem content as oemtest1.txt  
   
	MemoWrit ( "D:\test\oemtest2.txt" , c  ) 

2). X# behaviour

MemoRead() uses System.IO.File.ReadAllText() and Memowrit() System.IO.File.WriteAllText(), but no encoding is used. So i think something like this is required:

 
 FUNCTION MemoWrit(cFile AS STRING,c AS STRING) AS LOGIC
	LOCAL lOk AS LOGIC 
	
...
      
      IF SetAnsi()    //  <------ 
      
   		System.IO.File.WriteAllText(cFile, c) 
   
		ELSE

		   System.IO.File.WriteAllText(cFile, c , System.Text.Encoding.GetEncoding(RuntimeState:DosCodepage))  // <----
    
		ENDIF 
        
...
	
RETURN lOk
 
 
 
FUNCTION MemoRead(cFile AS STRING) AS STRING
	LOCAL cResult AS STRING 
	
...
			
			IF SetAnsi()  // <------
			
				cResult := System.IO.File.ReadAllText(cFile)
				
			ELSE
			 
				cResult := System.IO.File.ReadAllText(cFile,System.Text.Encoding.GetEncoding(RuntimeState:DosCodepage) )  // <-----
		
			ENDIF
			 	
...
	
RETURN cResult

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 3 weeks ago #5

Karl,

Here is my C# function to read a text file using FileStream and StreamReader which uses Encoding.Default.

public string ReadTextFile(string sFile)
{
string text = "";
var fileStream = new FileStream(@sFile, FileMode.Open, FileAccess.Read);
using (var streamReader = new StreamReader(fileStream, Encoding.Default))
{
text = streamReader.ReadToEnd();

}
return text;
}

Jamal

Please Log in or Create an account to join the conversation.

Last edit: by Jamal.

Insert text at top of a file 2 months 3 weeks ago #6

Hi Jamal,

the problem is your "Encoding.Default" usage. With your func i have no chance to get a correct conversion. To see
my "umlaute" with your func i would need - if setansi() is set to false - a RuntimeState:DosCodepage encoding. Here this codepage is 850. So when i change your code to:

StreamReader { fileStream, System.Text.Encoding.GetEncoding(850) }

is see my "umlaute" correctly.

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 3 weeks ago #7

Hi Karl,

I am in the US so I do not have to use "umlautes", however, in my case I was creating HTML files and when I used MemoRead(), it always inserted  at the beginning of the first line and thus I had to resort to .NET to fix the issue. I assume that MemoRead is actually using Win32 ReadFile() function because it exhibited the same behavior.

Jamal

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 2 weeks ago #8

Jamal,
MemoRead in the X# runtime uses managed file functions to load the text.

You can see the source for this function in our Git Repo:
github.com/X-Sharp/XSharpPublic/blob/fea...ctions/Memo.prg#L373

Since we are not passing an encoding then the .net runtime will try to determinge the file format. This usually works quite well.
See docs.microsoft.com/en-us/dotnet/api/syst...lText_System_String_ for more info about what the function in the .Net runtime does.
I have no idea why you see extra characters in your string, I would need to know the active codepage on your machine and would have to see the contents of the file.

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 2 weeks ago #9

I did a quick check with IlSpy and Vulcan uses FOpen() and FREad() to read the file inside MemoRead() and then translates the files from bytes to unicode with Mem2String().

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 2 weeks ago #10

robert wrote: I did a quick check with IlSpy and Vulcan uses FOpen() and FREad() to read the file inside MemoRead() and then translates the files from bytes to unicode with Mem2String().

Robert


Hi Robert,

I just tried it. VOs memoread() and memowrit() do a binary read/write

LOCAL c AS STRING

c := MemoRead ( "d:\test\AZG232849601_002_20181228.pdf")

? MemoWrit ( "d:\test\memowrite.pdf" , c )

never did something like this with VO before, but the created memowrite.pdf has exactly the same size and can be opened by a pdf viewer without problems. This is of course not possible with currently used System.IO.File.WriteAllText() and System.IO.File.ReadAllText() .

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 2 weeks ago #11

Karl-Heinz,
This is not possible and not wanted. People expect to be able to read an Ansi text file and see the contents as Unicode text in their app.
We can't support that and read/write binary files at the same time.

To do this in .Net you need to use System.IO.File.ReadAllBytes().
We could add a MemoReadBinary() and MemoWriteBinary() for that purpose, but that would just be a wrapper around ReadAllBytes() and WriteAllBytes().
Do you think this is needed ?

Robert

Note: of course these functions would not return or accept a string. Most likely a byte[].
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Last edit: by robert.

Insert text at top of a file 2 months 2 weeks ago #12

Hi Robert,

as i wrote, i never used MemoRead()/MemoWrit() this way before. But searching the intl VO google group shows that sometimes memoread() is used to read bitmaps from disk and show them in a FabControl ?

Personally i don´t expect and don´t need this VO behaviour, but finally it's your decision what to do. At least, it would be nice if WriteAllText() and .ReadAllText() would respect the SetAnsi() setting as i mentioned some msgs above.

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 2 weeks ago #13

Robert,

I was referring to VO's MemoRead not X#.

However, as to Karl's issue, I would suggest may be you can overload the MemoRead function in X#, i.e. (I assume this possible in X#, as I have not read the docs and dived deep into it).

MemoRead(cFile)
MemoRead(cFile, lSetAnsi)
MemoRead(cFile, lSetAnsi, uEncoding)

Jamal


However

Please Log in or Create an account to join the conversation.

Last edit: by Jamal.

Insert text at top of a file 2 months 3 weeks ago #14

Guys,

I agree, MemoRead() and MemoWrite() need to be adjusted as Karl-Heinz suggested, so that they can properly read ansi and oem text files depending on the SetAnsi() function, for compatibility with VO.

But for reading/writing binary data, only way to do it is by using more overloads as Jamal said, or provide different functions like MemoReadBinary() that Robert pointed out. using overloads has the disadvantage that one overload of MemoRead() needs to return a string and others need to return a byte array, so it can be confusing.

But, in any case, all that MemoRead() basically does is to call System.IO.File.ReadAllText(). So is it really worth it providing more overloads or more functions for that simple thing, or is it better to adjust such code so that it uses directly the appropriate .Net method for reading binary data? Anyway such code will need to be adjusted so that it uses a byte array as an intermediate buffer instead of a string, so I think it is more practical to also use directly the proper method (File.ReadAllBytes() for example).

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 3 weeks ago #15

Chris wrote: ... or is it better to adjust such code so that it uses directly the appropriate .Net method for reading binary data?

If we have a problem with .Net, it's the overwhelming mass of funcs - so, for this case, don't put another load on our brain ;)

my .1
Karl

Please Log in or Create an account to join the conversation.

Insert text at top of a file 2 months 3 weeks ago #16

Karl,
I have made the following changes:

1) Inside in MemoRead() and MemoWrit() the necessary conversion from 8 bit ansi or 8bit oem to unicode are done
2) I have added new functions MemoReadBinary() and MemoWritBinary() to work with the contents of binary files. The content is represented as an array of bytes (byte[]).

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

  • Page:
  • 1