Writing in binary files in Delphi - delphi

I'm making a program in delphi that writes data to a binary file and I have a problem I do not understand how to solve.
I have the following code:
testar: = TFileStream.Create ('test.exe', fmOpenWrite);
testar.Position: = testar.Size;
here: = '{test} test {test}';
testar.Write (here, 1024);
Tested with WinHex
http://img836.imageshack.us/img836/3206/la49.jpg
This edition fine prints in the binary code because when I see it with WinHex looks good, but this other code:
testar: = TFileStream.Create ('test.exe', fmOpenWrite);
testar.Position: = testar.Size;
here: = '{test}' + Edit1.Text + '{test}';
testar.Write (here, 1024);
It does not show anything at all because it seems that there is a problem with the edit when you want to edit the binary code, it's weird because when
I use it all goes single quotes but with the example of the edit does not work.
Note: The program does not give any error message
Someone could help me with this problem ?

You have provided non-real code, but I suspect that "here" is string.
To write string body to stream, you can use the next code:
test.Write(PChar(here)^, SizeOf(Char) * Length(here));
P.S. If you are going to read this string from stream (file) later, then it would be wise to write its length before string body.

Related

Reading characters within a file (the fseek command) not working in nxc (not-exactly-c) programming

Basically I'm trying to write code that reads a specified value from a file ex: file contains(12345) the code reads specific place (say the 3rd place) and the output = 3
I already know how to write numbers to a file but I am stuck on how to read a character because the fseek command won't work (it doesn't know what the command is). I downloaded the include folder with all the extra commands but it still couldn't find the file "stdio.h" in the code.
I don't completely know how it all works anyway
I am a complete noob in programing and so I only know the very basic stuff. I am 90% sure it is my fault it isn't working.
#include "cstdio.h." //gets error (doesn't recognize command/file)
task main ()
{
byte handle;
int fsize = 100;
int in;
int sus = 12345;
DeleteFile("int.txt");
CreateFile("int.txt",100,handle);
Write(handle, sus);
CloseFile(handle);
OpenFileRead("int.txt",fsize,handle);
fseek(handle, 10, 3); //gets error (doesn't recognize command)
in = fgetc(handle);
ClearScreen();
NumOut(30,LCD_LINE5,in);
Wait(100000);
CloseFile(handle);
}

How do I work with Word Documents without using COM Automation?

I have read multiple posts on the issue, and none seem to come to a decent conclusion to my question. (Perhaps I'm trying to see if anything has popped up lately.)
I have a small charity app that handles pledges. In doing so, it needs to work with and print documents.
Thing is, if Word is open in the background, the app thread will hang and won't respond to the closure of Word, and I have to roll back manually and close word. Sure, that all works fine, but I simply cannot guarantee that the end user will close Word, even if I put the instruction in a user manual.
I'm not too fussed about speed, but I guess that if it can be enhanced, it would be a nice little bonus.
Have any libraries been released for Delphi that will allow me to open, edit, print, and save documents? If not, is there a way to use Word Automation in such a way that it will not conflict with another open handle of Word when opened?
If you use GetActiveOleObject, you will get the running instance of Word.
By using CreateOleObject, you will get a new instance and shouldn't be troubled by other running instances.
In case you use the TWordApplication, wrapper you can set ConnectKind to ckNewInstance to accomplish this. By default, TWordApplication will try to connect with a running instance.
If you want to open edit and print Word documents and you don't mind using RTF format for what you're doing, investigate TRichView.
It will generate rich documents that are in RTF format, which is one of the formats MS word supports. I don't think it directly reads .DOC files but you can convert .DOC and .DOCX into RTF, for most simple files, but certain advanced formatting features would be lost in the conversion.
It has the advantage of working without any need for even any copy of MS Word to be installed on the machine that is going to do the document processing. For production of receipts and other simple documents, this would be the most reliable technique; Don't use Word directly, at all.
procedure PrintViaWord (const filename: string);
const
wdUserTemplatesPath = 2;
var
wrdApp, wrdDoc, wrdSel: variant;
begin
wrdApp:= CreateOleObject ('Word.Application'); // create new instance
sleep (5000); // this fixes a bug in Word 2010 to do with opening templates
wrdDoc:= wrdApp.documents.add (
wrdApp.Options.DefaultFilePath[wdUserTemplatesPath] + '\mytemplate.dot');
wrdDoc.Select;
wrdSel:= wrdApp.selection;
wrdApp.Options.CheckSpellingAsYouType:= 0;
wrdSel.paragraphformat.alignment:= 1;
wrdSel.typetext ('This is a program demonstrating how to open Word in the background'
+ ' and add some text, print it, save it and exit Word');
wrdDoc.SaveAs (filename + '.doc');
wrdApp.ActivePrinter:= 'Konica Minolta 211';
wrdApp.PrintOut;
WrdDoc.SaveAs (filename + '.doc');
wrdApp.quit;
wrdSel:= unassigned;
wrdDoc:= unassigned;
wrdApp:= unassigned
end;

Delphi 7 - Decode Base64 Using TIdDecoderMIME

OK, well this is driving me nuts, lol.
I have a Base64 string and am trying to decode it into a TMemoryStream using TIdDecoderMIME.
My current code is as follows:
Var MStream:TMemoryStream; Decoder:TIdDecoderMIME;
begin
Decoder := TIdDecoderMIME.Create(nil);
MStream := TMemoryStream.Create;
Decoder.DecodeToStream(BSting,MStream);
end;
Where BString = My Base64 string.
Now when the code is ran, I get an error message saying "Uneven size in DecodeToString."
Any ideas?
Any help is greatly appreciated. Thanks.
You're passing to the DecodeToStream function a Base64 string whose length is not a multiple of 4. In other words, the string you're passing is invalid.
Base64 strings are normally padded with trailing "=" signs to make sure their length is a multiple of 4.
Some decoders will try to correct for the missing padding chars while others will not. See the StackOverflow question "Remove trailing “=” when base64 encoding"
The TIdDecoderMime object validates the input by making sure it is a multiple of 4 - which it will be if the padding chars are included in the input.

KaZip for C++Builder2009/Delphi

I have download and install KaZip2.0 on C++Builder2009 (with little minor changes => only set type String to AnsiString). I have write:
KAZip1->FileName = "test.zip";
KAZip1->CreateZip("test.zip");
KAZip1->Active = true;
KAZip1->Entries->AddFile("pack\\text.txt","xxx.txt");
KAZip1->Active = false;
KAZip1->Close();
now he create a test.zip with included xxx.txt (59byte original, 21byte packed). I open the archiv in WinRAR successful and want open the xxx.txt, but WinRAR says file is corrupt. :(
What is wrong? Can somebody help me?
Extract not working, because file is corrupt?
KAZip1->FileName = "test.zip";
KAZip1->Active = true;
KAZip1->Entries->ExtractToFile("xxx.txt","zzz.txt");
KAZip1->Active = false;
KAZip1->Close();
with little minor changes => only set
type String to AnsiString
Use RawByteString instead of AnsiString.
I have no idea how KaZip2.0 is implemented, but in general, to make a Delphi/C++ library that was designed without Unicode support in mind working properly you need to do two things:
Replace all Char with AnsiChar and all string to AnsiString
Replace all Win API calls with their Ansi variant, i.e. replace AWin32Function with AWin32FunctionA.
In Delphi < 2009, Char = AnsiChar, String = AnsiString, AWin32Function = AWin32FunctionA, but in Delphi >= 2009, by default, Char = WideChar, String = UnicodeString, AWin32Function = AWin32FunctionW.
WinRAR could be simply failing to recognize the header. Try opening it in Windows or some other zip programs.
with little minor changes => only set
type String to AnsiString
That's doesn't work always right, it may compile but it doesn't mean it will work right in D2009 or CB2009, you need to show the places that you convert Strings to AnsiStrings, specially the code deal with : Buffers, Streams and I/O.
It's not surprising that your code is wrong; KaZip has no documentation.
Proper code is:
//Create a new empty zip file
KAZip1->CreateZip("test.zip");
//Open our newly created zip file so we can add files to it
KAZIP1->Open("test.zip");
//Compress text.txt into xxx.txt
KAZip1->Entries->AddFile("pack\\text.txt","xxx.txt");
//Close the file stream
KAZip1->Close();

Opening File paths with spaces in Delphi 5

(Using Delphi 5)
I am attempting to open a log file using the following code:
// The result of this is:
// C:\Program Files\MyProgram\whatever\..\Blah\logs\mylog.log
fileName := ExtractFilePath(Application.ExeName) + '..\Blah\logs\mylog.log';
// The file exists check passes
if (FileExists(fileName)) then
begin
logs := TStringList.Create();
// An exception is thrown here: 'unable to open file'
logs.LoadFromFile(fileName);
end;
If I relocate the log file to C:\mylog.log the code works perfectly. I'm thinking that the spaces in the file path are messing things up. Does anyone know if this is normal behavior for Delphi 5? If it is, is there a function to escape the space or transform the path into a windows 8.3 path?
I'm pretty sure that Delphi 5 handles spaces in filenames ok but it has been a very long time since I have used that specific version. Is the file currently open by another process? It also could be a permissions issue. Can you instead of loading it into a tStringList, try opening it with a tFileStream with the filemode set to "fmOpenRead or fmShareDenyNone".
fStm := tFileStream.Create( filename, fmOpenRead or fmShareDenyNone );
then load your tStringlist from the stream:
Logs.LoadFromStream ( fStm );
Are you sure its not the "..\" thats causing the problem rather than the spaces. Have you tried to see if it works at
c:\My\Path\nospaces\
If so and you are always using the ..\ path, maybe write a simple function to remove the last folder from your application path and create a full correct pathname.
It's odd that Delphi 5 would throw errors about this. I know of an issue with FileExists failing on files with an invalid last-modified-date (since it internally uses FileAge), but it's the opposite here. Instead of using "..\" I would consider risking the current path, and loading from a relative path: LoadFromFile('..\Something\Something.log'); especially for smaller applications, or by calling ExtractFilePath twice: ExtractFilePath(ExtractFilePath(Application.ExeName))
I'm pretty sure Delphi has always handled spaces so I doubt that is the issue.
You don't show the full path. Any chance it is really long? For example I could believe an issue with paths longer than 255 characters.
It's also a bad idea to put log files under Program Files. Often normal users are not given permission to write to anything under Program Files.
Delphi 5 can open files with spaces - that is certainly not the problem. To prove it, try copying it to c:\my log.log- it should open fine.
Is there any more information in the error message you receive? The most likely thing is that someone else (perhaps your own program) is still writing to the log.
The spaces are not a problem. While the '..' could be a problem in Delphi 5, mosts probably the file is locked by the process that writes to it. If you have control of it, make sure it opens the file with fmShareDenyWrite and not fmShareExclusive or fmShareCompat (which is the default).
Also, you can use:
fileName := ExpandFileName(ExtractFilePath(Application.ExeName) + '..\Blah\logs\mylog.log');
to obtain the absolute path from a relative path.
Also, as others have said, it is not good idea to write anything in Program Files. Regular users (that are not Administrators or Power Users) do not have rights to write there (although in Vista is will be virtualized, is is still not a good idea). Use the appropriate Application Data folder for the user (or all users). This folder can be obtained using:
SHGetFolderPath(0,folder,0,SHGFP_TYPE_CURRENT,#path[0])
where folder is either CSIDL_COMMON_APPDATA or CSIDL_LOCAL_APPDATA. See this delphi.about.com article for an example.
Simple :
// if log file = "C:\Program files\mylog.log"
// you'll get :
// »»»»» fileName = 'C:\Program files..\Blah\logs\mylog.log'
// if log file = "C:\mylog.log"
// you'll get :
// »»»»» fileName = 'C:..\Blah\logs\mylog.log'
Try this code instead, I'm pretty sure it will fit your needs :
fileName := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName))
+ '..\Blah\logs\mylog.log';
Regards,
Olivier
Delphi 5 has never had a problem opening files with spaces and I am still using it since it is uber stable and works great for older XP apps. You need to check your code closely.

Resources