|
Home > Archive > Unix Programming > January 2006 > How to set EOF of a file?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
How to set EOF of a file?
|
|
| vansky 2006-01-19, 8:11 am |
| hi all,
im implementing the following func:
CFile.SetLength(int len)
{
....
Seek(len, begin);
fputc(EOF, m_hFile);
}
but after runing, i use vi to open SetLengthed file and find it didnt
work!
Why and How?
thx!
Best,
| |
| Barry Margolin 2006-01-19, 8:11 am |
| In article <1137661085.764923.95930@g47g2000cwa.googlegroups.com>,
"vansky" <huangms_van@hotmail.com> wrote:
> hi all,
>
> im implementing the following func:
>
> CFile.SetLength(int len)
> {
> ...
>
> Seek(len, begin);
>
> fputc(EOF, m_hFile);
>
> }
>
> but after runing, i use vi to open SetLengthed file and find it didnt
> work!
>
> Why and How?
EOF isn't a real character, you can't write it to a file. It's a
special value that fgetc(3) returns when it has reached the end of the
file.
Use ftruncate(2).
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| SM Ryan 2006-01-19, 8:11 am |
| "vansky" <huangms_van@hotmail.com> wrote:
# hi all,
#
# im implementing the following func:
#
# CFile.SetLength(int len)
# {
# ...
#
# Seek(len, begin);
#
# fputc(EOF, m_hFile);
#
# }
#
# but after runing, i use vi to open SetLengthed file and find it didnt
# work!
Because a Unix end of disk file is not a particular character or mark
within the file. The system keeps tracks of the current number of bytes
in the file and any read beyond that returns an end of file indication.
You set the disc file length with an ftruncate or similar call that
lets you tell the system what the current length is.
Other kinds of files have different of end of file conditions, or
(like a serial port) they never have an end of file. For example a
terminal file returns an end of file on control-D, a tape drive on
a tape mark, etc.
--
SM Ryan http://www.rawbw.com/~wyrmwif/
I think that's kinda of personal; I don't think I should answer that.
| |
| vansky 2006-01-19, 8:11 am |
| hey,
thanks!
i cound not find these funcs such as ftruncate, fstat in all my
references!
could u recommend some great references about programming on linux?
thx a lot!
Best Regards!
| |
|
|
| Pascal Bourguignon 2006-01-19, 6:24 pm |
| "vansky" <huangms_van@hotmail.com> writes:
> hey,
>
> thanks!
>
> i cound not find these funcs such as ftruncate, fstat in all my
> references!
>
> could u recommend some great references about programming on linux?
If:
man ftruncate
doesn't produce the manual page of ftruncate on your unix system, then
you need to install the package containing the manual pages. They
usually come with the developer tools...
--
__Pascal Bourguignon__ http://www.informatimago.com/
"Debugging? Klingons do not debug! Our software does not coddle the
weak."
| |
| vansky 2006-01-19, 8:50 pm |
| thx!! Sel=E5sdal
hi Bourguignon,
thx, i love comm "man",
the problem is:
i dont know the func "fruncate" is provided at all !=20

| |
| Pascal Bourguignon 2006-01-19, 8:50 pm |
| "vansky" <huangms_van@hotmail.com> writes:
> thx!! Selåsdal
>
> hi Bourguignon,
>
> thx, i love comm "man",
>
> the problem is:
>
> i dont know the func "fruncate" is provided at all !
>
> 
The Linux ftruncate manual page indicates that ftruncate is:
CONFORMING TO
4.4BSD, SVr4 (these function calls first appeared in BSD 4.2).
POSIX 1003.1-1996 has ftruncate. POSIX 1003.1-2001 also has
truncate, as an XSI extension.
So if your system is not 4.4BSD, 4.5BSD, SVr4, or POSIX 1003.1-1996
compliant, perhaps you should specify more precisely what OS you're
using?
--
__Pascal Bourguignon__ http://www.informatimago.com/
HANDLE WITH EXTREME CARE: This product contains minute electrically
charged particles moving at velocities in excess of five hundred
million miles per hour.
| |
| vansky 2006-01-19, 8:50 pm |
| hi Bourguignon,
the OS is fedora 4, and the designed SW is supposed to run well ON
RedHad 7.2 - Fedora 4, RH Enterprise 3, SuSE 8 - SuSE 9.2, and Debian
3.
And i havnt got enough time to focus on Compatibility up to now. and i
know little about 4.4BSD, SVr4, etc.
do u have any advice for me?
btw, i used like turncate("/test/tmp", LEN),
coz func: ftruncate(int fd, off_t len), i dont know how to get the
para "fd", :-(
thx.
| |
| Pascal Bourguignon 2006-01-20, 2:50 am |
| "vansky" <huangms_van@hotmail.com> writes:
> hi Bourguignon,
>
> the OS is fedora 4, and the designed SW is supposed to run well ON
> RedHad 7.2 - Fedora 4, RH Enterprise 3, SuSE 8 - SuSE 9.2, and Debian
> 3.
>
> And i havnt got enough time to focus on Compatibility up to now. and i
> know little about 4.4BSD, SVr4, etc.
>
> do u have any advice for me?
>
> btw, i used like turncate("/test/tmp", LEN),
There is no way to turn any cate in Linux, including in Fedora. You
have to be much much more careful with spelling: computers don't
forgive. Try it, it's not too difficult. Type letter by letter the
text:
The OS is Fedora 4, and the designed software is supposed to run
well ON RedHad 7.2 - Fedora 4, RH Enterprise 3, SuSE 8 - SuSE 9.2,
and Debian 3.
And I haven't got enough time to focus on compatibility up to now.
And I know little about 4.4BSD, SVr4, etc.
Do you have any advice for me?
By the way, I used something like: truncate("/test/tmp",LEN)
because for the function: ftruncate(int fd,off_t len), I don't
know how to get the parameter "fd", :-(
It was not too hard, was it?
> coz func: ftruncate(int fd, off_t len), i dont know how to get the
> para "fd", :-(
Then you need to learn more about the basics of unix application
programming. There are a lot of tutorials and books on the web.
http://www.google.com/search?q=tuto...nix+programming
In the mean time, note that man truncate says:
With ftruncate, the file must be open for writing; with truncate,
the file must be writable.
and thus tells you that you could use the open function.
man 2 open
int fd=open("/tmp/test",O_RDWR,0);
if(fd>=0){
int res=ftruncate(fd,LEN);
if(res<0){
perror("ftruncate");
}
do_something_with_truncated_file(fd);
close(fd);
}else{
perror("open");
}
--
__Pascal Bourguignon__ http://www.informatimago.com/
What is this talk of 'release'? Klingons do not make software 'releases'.
Our software 'escapes' leaving a bloody trail of designers and quality
assurance people in it's wake.
| |
| vansky 2006-01-20, 2:50 am |
| Hi Bourguignon,
Thanks! You are definitely a great teacher!
And sorry for careless typing.
I have to work over 12 hours per day recently. So busy and so tired !
Final code is:
void CMyFile::SetLength(DWORD dwNewLen)
{
ASSERT(m_hFile != (HNDFILE)hFileNull);
Seek((LONG)dwNewLen, (UINT)begin);
#ifdef __LINUX_VER__
truncate(m_strFileName, dwNewLen);
fflush(m_hFile);
#else
::SetEndOfFile((HANDLE)m_hFile);
#endif
}
Best Regards!
| |
| vansky 2006-01-20, 2:50 am |
| Hi Bourguignon,
Thanks! You are definitely a great teacher!
And sorry for careless typing.
I have to work over 12 hours per day recently. So busy and so tired !
Final code is:
void CMyFile::SetLength(DWORD dwNewLen)
{
ASSERT(m_hFile != (HNDFILE)hFileNull);
Seek((LONG)dwNewLen, (UINT)begin);
#ifdef __LINUX_VER__
truncate(m_strFileName, dwNewLen);
fflush(m_hFile);
#else
::SetEndOfFile((HANDLE)m_hFile);
#endif
}
Best Regards!
| |
| Pascal Bourguignon 2006-01-20, 2:50 am |
| "vansky" <huangms_van@hotmail.com> writes:
> Final code is:
>
> void CMyFile::SetLength(DWORD dwNewLen)
> {
> ASSERT(m_hFile != (HNDFILE)hFileNull);
>
> Seek((LONG)dwNewLen, (UINT)begin);
>
> #ifdef __LINUX_VER__
> truncate(m_strFileName, dwNewLen);
> fflush(m_hFile);
> #else
> ::SetEndOfFile((HANDLE)m_hFile);
> #endif
> }
AFAIK, MS-Windows is also POSIX compliant (fsvo "compliant").
At the OS level, you have what unix calls file descriptors (fd): they
are small integers, what's called "a handle" in MS-Windows.
They are manipulated with the system calls: open, read, write, close,
and a few others like ftruncate and lseek.
Over this OS layer, there is the C standard library, including stdio,
which define the FILE structure and fopen, fread, fwrite, fclose,
fprintf, fseek, etc functions, which take a pointer to a FILE
structure, like for example, the variables stdin, stdout and stderr.
This IO layer is often buffered.
Seek((LONG)dwNewLen, (UINT)begin) won't work on unix. There's no
function named Seek.
Since you're writting in C++, I'd define an abstract class (CMyFile),
and two concrete classes: CMSWindowsFile and CUnixFile (or CPosixFile)
or CStdIOFile. Then instead of having a lot of #ifdef, you'd just
select the right component in the standard software component
management program: make. The makefile would contain something like:
COMMON_OBJECT=CMyFile.o ...
WINDOWS_OBJECT=CMSWindowsFile.o ...
UNIX_OBJECTS=CUnixFile.o ...
win32: $(COMMON_OBJECTS) $(WINDOWS_OBJECTS)
ld -o pgm.exe $(COMMON_OBJECTS) $(WINDOWS_OBJECTS) $(WINDOWS_LIBRARIES)
unix: $(COMMON_OBJECTS) $(UNIX_OBJECTS)
ld -o pgm $(COMMON_OBJECTS) $(UNIX_OBJECTS) $(UNIX_LIBRARIES)
and you would just type:
make win32
on MS-Windows, or:
make unix
on UNIX, to compile the program with the right components.
The only thing you'd need in the source is to add some factory objects
(or just factory functions):
Instead of writing: CMyFile* file=new CMyFile(...);
you'd write: CMyFile* file=CMyFile::makeInstance(...);
typedef CMyFile* (*CMyFile_FactoryPr)(...);
extern CMyFile_FactoryPr CMyFile_Factory;
CMyFile* CMyFile::makeInstance(...){ return(CMyFile_Factory(...)); }
And in CMSWindowsFile:
CMyFile* CMSWindowsFile_Factory(...){ return(new CMSWindowsFile(...)); }
CMyFile_FactoryPr CMyFile_Factory=CMSWindowsFile_Factory;
And in CUnixFile:
CMyFile* CUnixFile_Factory(...){ return(new CUnixFile(...)); }
CMyFile_FactoryPr CMyFile_Factory=CUnixFile_Factory;
Since by the Makefile only one of CMSWindowsFile or CUnixFile is
linked at a time, there's no conflict in the definition and
initialization of CMyFile_Factory.
Also, you can write some #define macros to ease the generation of the
above pattern.
Instead of targetting unix, you may target a POSIX OS (there are more
POSIX OS than unix OS), or even the standard C library (there are more
system with a C compiler and its standard library than POSIX systems).
The POSIX and Standard C classes could even be compiled on MS-Windows.
Finally, there already exist a few libraries allowing you to develop
code common on unix and MS-Windows. Apache (the web server) contains
one. You will find them easily with google.
--
__Pascal Bourguignon__ http://www.informatimago.com/
HEALTH WARNING: Care should be taken when lifting this product,
since its mass, and thus its weight, is dependent on its velocity
relative to the user.
| |
| vansky 2006-01-20, 2:50 am |
| Hi Bourguignon,
I have learned a lot from you! Thanks very much!
I'm porting a Windows program to Linux which has about 40k lines. Most
coding work has been done and I'm debuging and testing it now.
It's true that the function Seek is not provided. And I have rewrite it
as following.
LONG CMyFile::Seek(LONG lOff, UINT nFrom)
{
ASSERT(m_hFile != (HNDFILE)hFileNull);
ASSERT(nFrom == begin || nFrom == end || nFrom == current);
ASSERT(begin == FILE_BEGIN && end == FILE_END && current ==
FILE_CURRENT);
DWORD dwNew;
#ifdef __LINUX_VER__
fseek(m_hFile, lOff, nFrom);
dwNew = ftell(m_hFile);
#else
dwNew = ::SetFilePointer((HANDLE)m_hFile, lOff, NULL, (DWORD)nFrom);
#endif
return dwNew;
}
Definitely, I'll be grateful to you for your abstract class CMyFile for
my studying.
I love cross-platform programming with C++ and love such framework/code
such as wxwidgets, apache, etc.
On porting, I found the character set rewriting comsume most of my
time.
1) Unicode wide char is UCS2 (2 bytes) on Windows, but is UCS4 (4
bytes) on Linux.
2) TCHAR: it's well support on Win, but on Linux, we can't:
fopen(TCHAR *path,...)
3) such as lstrcpy(lstrcpyA, lstrcpyW), lstrcmp series. -- done, wait
for testing
4) wide char functions: _wcsicmp(), _wcsicoll() -- done, wait for
testing
5) MBS functions: _mbscmp() -- done, wait for testing
6) OEM & ANSI, such as OemToAnsi(), -- have no idea, and will not
support that. :-)
Best Regards!
| |
| vansky 2006-01-20, 2:50 am |
| Hi Bourguignon,
I have learned a lot from you! Thanks very much!
I'm porting a Windows program to Linux which has about 40k lines. Most
coding work has been done and I'm debuging and testing it now.
It's true that the function Seek is not provided. And I have rewritten
it
as following.
LONG CMyFile::Seek(LONG lOff, UINT nFrom)
{
ASSERT(m_hFile != (HNDFILE)hFileNull);
ASSERT(nFrom == begin || nFrom == end || nFrom == current);
ASSERT(begin == FILE_BEGIN && end == FILE_END && current ==
FILE_CURRENT);
DWORD dwNew;
#ifdef __LINUX_VER__
fseek(m_hFile, lOff, nFrom);
dwNew = ftell(m_hFile);
#else
dwNew = ::SetFilePointer((HANDLE)m_hFile, lOff, NULL,
(DWORD)nFrom);
#endif
return dwNew;
}
Definitely, I'll be grateful to you for your abstract class CMyFile for
my studying.
I love cross-platform programming with C++ and love such framework/code
such as wxwidgets, apache, etc.
On porting, I found the character set functions rewriting comsume most
of my time.
1) Unicode wide char is UCS2 (2 bytes) on Windows, but is UCS4 (4
bytes) on Linux.
2) TCHAR: it's well supported on Win, but on Linux, we can't:
fopen(TCHAR *path,...)
3) such as lstrcpy(lstrcpyA, lstrcpyW), lstrcmp series. --
done, wait
for testing
4) wide char functions: _wcsicmp(), _wcsicoll() -- done, wait
for
testing
5) MBS functions: _mbscmp() --
done, wait for testing
6) OEM & ANSI, such as OemToAnsi(), -- have no idea, and will not
support that. :-)
Best Regards!
| |
| Pascal Bourguignon 2006-01-20, 8:14 am |
| "vansky" <huangms_van@hotmail.com> writes:
> Hi Bourguignon,
>
> I have learned a lot from you! Thanks very much!
>
> I'm porting a Windows program to Linux which has about 40k lines. Most
> coding work has been done and I'm debuging and testing it now.
>
> It's true that the function Seek is not provided. And I have rewrite it
> as following.
>
> LONG CMyFile::Seek(LONG lOff, UINT nFrom)
> {
> ASSERT(m_hFile != (HNDFILE)hFileNull);
>
> ASSERT(nFrom == begin || nFrom == end || nFrom == current);
> ASSERT(begin == FILE_BEGIN && end == FILE_END && current ==
> FILE_CURRENT);
>
> DWORD dwNew;
> #ifdef __LINUX_VER__
> fseek(m_hFile, lOff, nFrom);
> dwNew = ftell(m_hFile);
> #else
> dwNew = ::SetFilePointer((HANDLE)m_hFile, lOff, NULL, (DWORD)nFrom);
> #endif
> return dwNew;
> }
Then m_hFile is a FILE* in your unix port, and you can get the file
descriptor under this FILE structure with the fileno function.
int res=ftruncate(fileno(m_hfile),SIZE);
should work.
> On porting, I found the character set rewriting comsume most of my
> time.
>
> 1) Unicode wide char is UCS2 (2 bytes) on Windows, but is UCS4 (4
> bytes) on Linux.
>
> 2) TCHAR: it's well support on Win, but on Linux, we can't:
> fopen(TCHAR *path,...)
Usually, we use UTF-8 to encode the files. In the program you can
expand it as easily to UCS4 as to USC2.
You can use the iconv command to convert files,
and libiconv in the programs.
http://www.gnu.org/software/libiconv/
>
> 3) such as lstrcpy(lstrcpyA, lstrcpyW), lstrcmp series. -- done, wait
> for testing
>
> 4) wide char functions: _wcsicmp(), _wcsicoll() -- done, wait for
> testing
>
> 5) MBS functions: _mbscmp() -- done, wait for testing
>
> 6) OEM & ANSI, such as OemToAnsi(), -- have no idea, and will not
> support that. :-)
What does it do?
--
__Pascal Bourguignon__ http://www.informatimago.com/
NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
| |
| Giorgos Keramidas 2006-01-20, 6:03 pm |
| On 19 Jan 2006 17:14:23 -0800, "vansky" <huangms_van@hotmail.com> wrote:
> thx!! Selåsdal
>
> hi Bourguignon,
>
> thx, i love comm "man",
>
> the problem is:
>
> i dont know the func "fruncate" is provided at all !
On most UNIX systems that have manpages installed, there is some sort of
search facility for the manpages, i.e.:
kobe:/home/keramida$ man -k file | egrep -e 'size|length'
growfs(8) - grow size of an existing ufs file system
newsyslog(8) - maintain system log files to manageable sizes
truncate(1) - truncate or extend the length of files
truncate(2), ftruncate(2) - truncate or extend a file to a specified length
kobe:/home/keramida$
You can use `man -k' to look for specific patterns. It usually works
better for me if the `man -k' pattern is general enough, and egrep(1) is
used later on to refine the search, after I've seen some of the results.
- Giorgos
| |
| Barry Margolin 2006-01-21, 2:49 am |
| In article <87bqy7lkia.fsf@thalassa.informatimago.com>,
Pascal Bourguignon <spam@mouse-potato.com> wrote:
> "vansky" <huangms_van@hotmail.com> writes:
>
>
> The Linux ftruncate manual page indicates that ftruncate is:
I think you misunderstood him. His point was that RTFM isn't a very
helpful suggestion if you don't know the name of the function, or even
that such a function exists. The manual is great if you just need a
reference for the details of how to call a function, but not a very good
way to learn how to do things in the first place.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| vansky 2006-01-21, 2:49 am |
| To Bourguignon:
About TCHAR, Unicode, MBS, and WCHAR:
introduced in < Advanced String Techniques in C++ >
URL: http://www.flipcode.com/articles/ar...strings01.shtml
or "man wcstombs", or view wchar.h
OEM (original equipment manufacturer)
The OEM character set is typically used in full-screen MS-DOS?sessions
for screen display. Characters 32 through 127 are usually the same in
the OEM, U.S. ASCII, and Windows character sets. The other characters
in the OEM character set (0 through 31 and 128 through 255) correspond
to the characters that can be displayed in a full-screen MS-DOS
session. These characters are generally different from the Windows
characters.
Localization, lstrcmp:
The language (user locale) selected by the user at setup time, or
through Control Panel, determines which string is greater (or whether
the strings are the same). If no language (user locale) is selected,
the system performs the comparison by using default values.
With a double-byte character set (DBCS) version of the system, this
function can compare two DBCS strings.
The lstrcmp function uses a word sort, rather than a string sort. A
word sort treats hyphens and apostrophes differently than it treats
other symbols that are not alphanumeric, in order to ensure that words
such as "coop" and "co-op" stay together within a sorted list. For a
detailed discussion of word sorts and string sorts, see the Remarks
section for the CompareString function.
Windows 95/98/Me:??? lstrcmpW is supported by the Microsoft Layer for
Unicode. To use this, you must add certain files to your application,
as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems.
Best,
| |
| vansky 2006-01-21, 2:49 am |
| To Keramidas:
that's great! thx!
To Margolin:
that's exactly what i wanna to express.
Best,
|
|
|
|
|