C言語初心者のy_615_tと申します。
秀丸というエディタで作っているソースを
Visual Studio.NET(2005)でコンパイルしています。
環境はwindowsXPです。
現在Win32APIをつかってプログラムを作っています。
2つのファイルを用意し、以下の状態を作ります。
(1)2つともない時
(2)1つめだけある時
(3)2つめだけある時
(4)2つともある時
この状態のとき、以下の処理をします。
(1)のとき、1つ目のファイルを作り、ファイルに書き込む
(2)のとき、1M以下なら続きから書き込む
1M以上なら2つ目のファイルを作り、書き込む
(3)のとき、(2)と同様
(4)のとき、サイズを比較して書き込む
サイズが同じ時、更新日時で比較して新しい方に書き込む
というプログラムを作りたいのですが、HANDLEが無効というエラーが出てしまいます。
サイズ・更新日時の取得に
・GetSizeFile
・GetFileTime
を使っているので、エラーが起こるのかなと思ったのですが、
上手く動作しません。
最初にファイルがルカのチェックをする際にサイズと時間をとっていて、処理の際に、比較しています。
書込みのWriteFileは外部関数として私が作ったものを呼び出しています。HANDLEのエラーは書込みの際起きているのですが、
HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか。教えてください。
A 回答 (6件)
- 最新から表示
- 回答順に表示
No.6
- 回答日時:
続き。
// ファイルが2つともない時
void WRITE_FILE0( LPWRITE_WORK w )
{
w->hFile1 = CREATE_FILE_NEW( Drct[0] );
SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );
HANDLE_WRITE1( w );
}
// ファイルが1つ目だけある時
void WRITE_FILE1( LPWRITE_WORK w )
{
if ( w->Size <= 1000 ){
SetFilePointer( w->hFile1, 0, NULL, FILE_END );
HANDLE_WRITE1( w );
}
else{
//CloseHandle( w->hFile1 );
w->hFile2 = CREATE_FILE_OPEN( Drct[1] );
SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );
HANDLE_WRITE2( w );
}
}
// ファイルが2つ目だけある時
void WRITE_FILE2( LPWRITE_WORK w )
{
if ( w->Size <= 1000 ){
SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );
HANDLE_WRITE2( w );
}
else{
//CloseHandle( w->hFile2 );
w->hFile1 = CREATE_FILE_OPEN( Drct[0] );
SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );
HANDLE_WRITE1( w );
}
}
// ファイルが両方ある時
void WRITE_FILE3( LPWRITE_WORK w )
{
if ( w->Size < w->Size2 ){
if ( w->Size <= 1000 ){
SetFilePointer( w->hFile1, 0, NULL, FILE_END );
HANDLE_WRITE1( w );
}
else{
//CloseHandle( w->hFile1 );
w->hFile2 = CREATE_FILE_EXISTING( Drct[1] );
SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );
HANDLE_WRITE2( w );
}
}
else if ( w->Size > w->Size2 ){
if ( w->Size2 <= 1000 ){
SetFilePointer( w->hFile2, 0, NULL, FILE_END );
HANDLE_WRITE2( w );
}
else{
//CloseHandle( w->hFile2 );
w->hFile1 = CREATE_FILE_EXISTING( Drct[0] );
SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );
HANDLE_WRITE1( w );
}
}
else if ( w->Size == w->Size2 ){
ft = CompareFileTime( &ft_b, &ft_b2 );
if ( ft == +1 ){
if ( Size <= 1000 ){
SetFilePointer( w->hFile1, 0, NULL, FILE_END );
HANDLE_WRITE1( w );
}
else{
//CloseHandle( w->hFile1 );
w->hFile2 = CREATE_FILE_EXISTING( Drct[1] );
SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );
HANDLE_WRITE2( w );
}
}
else if ( ft == -1 ){
if ( w->Size2 <= 1000 ){
SetFilePointer( w->hFile2, 0, NULL, FILE_END );
HANDLE_WRITE2( w );
}
else{
//CloseHandle( w->hFile2 );
w->hFile1 = CREATE_FILE_EXISTING( Drct[0] );
SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );
HANDLE_WRITE1( w );
}
}
else{
printf( "error\n" );
}
}
}
おそくなりました。
本当に本当にありがとうございます!!
解決しました!!
とても細かく説明してくださり、大変勉強になりました。
きちんと勉強したいと思います。
ありがとうございました。
No.5
- 回答日時:
★アドバイス
>HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか。
↑
これには問題はないと思います。
それよりも HANDLE_OPEN() 関数が長いので分かりやすく複数のサブ関数に
処理を分けたほうが良いでしょう。例えば
switch ( y * 2 + x ){
case 0: // ファイルが2つともない時
case 1: // ファイルが1つ目だけある時
case 2: // ファイルが2つ目だけある時
case 3: // ファイルが両方ある時
}
という感じで。
・あと CreateFile() 関数の部分はマクロ関数を定義して分かりやすくしてみます。
#define CREATE_FILE_NEW(s) …
#define CREATE_FILE_OPEN(s) …
#define CREATE_FILE_EXISTING(s) …
という感じで。
その他、CreateFile() 関数の戻り値をチェックしてみて下さい。
それからどこまで(どの動作まで)は正常に書き込んでいるのかをチェックして下さい。
>ファイルは作れたのですが、
>2つのファイルが1kBでとまり、それ以降書き込めなくなってしまいます。
↑
これってソースにある
>if(Size<=1000){
とか
>if(Size2<=1000){
の 1000 が原因ではないの?
質問では 1M(バイト)ですよね。それならば
if ( Size <= (1024 * 1024) ){
じゃなのかな?
それとも Size は KB 単位なのでしょうか?
・とにかく下に4つのサブ関数と1つの HANDLE_OPEN() に分けたものを載せておきます。
これを元にコンパイル可能な状態に修正してから調査して下さい。
どの関数のどの場所までは正常か、ここから異常かなど。
// break 付きの case キーワード
#define CASE break;case
#define DEFAULT break;default
// マクロ関数
#define CREATE_FILE(s,n) CreateFile(s,GENERIC_WRITE|GENERIC_READ,0,NULL,n,FILE_ATTRIBUTE_NORMAL,NULL)
#define CREATE_FILE_NEW(s) CREATE_FILE(s,CREATE_NEW)
#define CREATE_FILE_OPEN(s) CREATE_FILE(s,OPEN_ALWAYS)
#define CREATE_FILE_EXISTING(s) CREATE_FILE(s,TRUNCATE_EXISTING)
// 作業変数の構造体を宣言
typedef struct WRITE_WORK {
HANDLE hFile1;
HANDLE hFile2;
DWORD Size1;
DWORD Size2;
:
その他、必要ならば記述
:
} WRITE_WORK, *LPWRITE_WORK;
// 関数のプロトタイプ宣言
extern void HANDLE_WRITE1( LPWRITE_WORK w );
extern void HANDLE_WRITE2( LPWRITE_WORK w );
extern void WRITE_FILE0( LPWRITE_WORK w );
extern void WRITE_FILE1( LPWRITE_WORK w );
extern void WRITE_FILE2( LPWRITE_WORK w );
extern void WRITE_FILE3( LPWRITE_WORK w );
// 見やすく書き直し
void HANDLE_OPEN( void )
{
WRITE_WORK w;
int x, y;
// ここにファイルがあるかのチェックの処理
w.Size1 = 記述;
w.Size2 = 記述;
// 状況で分岐
switch ( y * 2 + x ){
CASE 0: WRITE_FILE0( &w ); // ファイルが2つともない時
CASE 1: WRITE_FILE1( &w ); // ファイルが1つ目だけある時
CASE 2: WRITE_FILE2( &w ); // ファイルが2つ目だけある時
CASE 3: WRITE_FILE3( &w ); // ファイルが両方ある時
}
CloseHandle( w.hFile2 );
CloseHandle( w.hFile1 );
}
次の回答へ続く。
No.4
- 回答日時:
>2つのファイルが1kBでとまり、それ以降
おそらく1KBも書き込まれていません。。。
1KBというのは恐らくディスク上のサイズに過ぎず、
実際にファイルのプロパティからみれば
数バイト程度書き込まれている程度でしょう。
ハンドルがグローバル変数になっているのですが、
見たところ通信処理などがありそうですが、
スレッドなどは使用していないのでしょうか?
>HANDLE_WRITE
上記の関数で失敗しているということでしょうか?
とりあえず、GetLastErrorの値を随所に出力するようにし、
何の関数が、どの様なエラーコードで終了しているかを
調べることが重要です。
そうでした。
2つのファイルともに1KBでとまり、それ以降は何も出来ない状態でした。
スレッドの入ったプログラムにこの処理を入れようとしています。
正常に動くか、まずは小さいものを作ろうと思い、はじめました。
エラーはHANDLE_WRITE関数でおこっていて、ハンドルが無効という6番のエラーでした。
ご指摘ありがとうございました。
No.3
- 回答日時:
> ハンドルを閉じなかったのですが、いけないようですね。
解決したのでしょうか?
まあそれはおいときまして、コードを見せてくれと言ったのは
実際にAPIを呼び出していたり、ハンドルを渡している部分なんですが(^^;
この回答への補足
#include<stdio.h>
#include<winsock2.h>
#include<ws2tcpip.h>
#include<windows.h>
#include<stdlib.h>
#include<winbase.h>
//#define BUFFER_SIZE 256
extern void HANDLE_WRITE(void);
extern void HANDLE_WRITE2(void);
HANDLE hFile;
HANDLE hFile2;
void HANDLE_OPEN()
{
/*ここに宣言とファイルがあるかのチェックの処理が入ります。*/
/*状況を作る*/
/*ファイルが2つともない時*/
if(x==0&&y==0){
flag=0;
}
/*ファイルが1つ目だけある時*/
else if(x==1&&y==0){
flag=1;
}
/*ファイルが2つ目だけある時*/
else if(x==0&&y==1){
flag=2;
}
/*ファイルが両方ある時*/
else if(x==1&&y==1){
flag=3;
}
/*フラグ別の処理*/
if(flag==0){
hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(hFile,0,0,0);
HANDLE_WRITE();
}
else if(flag==1){
if(Size<=1000){
SetFilePointer(hFile,0,0,2);
HANDLE_WRITE();
}
else{
//CloseHandle(hFile);
hFile2=CreateFile(Drct[1],GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(hFile2,0,0,0);
HANDLE_WRITE2();
}
}
else if(flag==2){
if(Size<=1000){
SetFilePointer(hFile2,0,0,2);
HANDLE_WRITE2();
}
else{
//CloseHandle(hFile2);
hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(hFile,0,0,0);
HANDLE_WRITE();
}
}
else if(flag==3){
if(Size<Size2){
if(Size<=1000){
SetFilePointer(hFile,0,0,2);
HANDLE_WRITE();
}
else{
//CloseHandle(hFile);
hFile2=CreateFile(Drct[1],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(hFile2,0,0,0);
HANDLE_WRITE2();
}
}
else if(Size>Size2){
if(Size2<=1000){
SetFilePointer(hFile2,0,0,2);
HANDLE_WRITE2();
}
else{
//CloseHandle(hFile2);
hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(hFile,0,0,0);
HANDLE_WRITE();
}
}
else if(Size==Size2){
ft=CompareFileTime(&ft_b,&ft_b2);
if(ft==+1){
if(Size<=1000){
SetFilePointer(hFile,0,0,2);
HANDLE_WRITE();
}
else{
//CloseHandle(hFile);
hFile2=CreateFile(Drct[1],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(hFile2,0,0,0);
HANDLE_WRITE2();
}
}
else if(ft==-1){
if(Size2<=1000){
SetFilePointer(hFile2,0,0,2);
HANDLE_WRITE2();
}
else{
//CloseHandle(hFile2);
hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(hFile,0,0,0);
HANDLE_WRITE();
}
}
else{
printf("error\n");
}
}
}
CloseHandle(hFile);
CloseHandle(hFile2);
return ;
}
ファイルは作れたのですが、
2つのファイルが1kBでとまり、それ以降書き込めなくなってしまいます。
No.2
- 回答日時:
>GetSizeFile
こんな関数WIN32APIにあったかな。。。?
GetFileSize?
>HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか
在ります。
例としては、そのプロセスが複数実行された場合やファイルIOが遅延した場合などに発生します。同じプロセス内でもスレッド内で書き込みを
行っていたりするとなる場合があります。
Globalにハンドルを持つならばしっかり排他制御する必要があります。
オープン状態で書き込みを続ける場合は今回のように2つのファイルを
ロテートさせる必要がありますが、ファイル(HANDLE)をきちっと閉じたりしていますか?そうでない場合も今回のようなことが起こりえます。
#もう少し具体的にコードなどがあると良いと思います。。。
早速のご回答、ありがとうございます。
>こんな関数WIN32APIにあったかな。。。?
>GetFileSize?
すみません。GetFileSizeです。
>在ります。
>例としては、そのプロセスが複数実行された場合やファイルIOが遅延した場合などに発生します。同じプロセス内でもスレッド内で書き込み>を
>行っていたりするとなる場合があります。
>Globalにハンドルを持つならばしっかり排他制御する必要があります。
>オープン状態で書き込みを続ける場合は今回のように2つのファイルを
>ロテートさせる必要がありますが、ファイル(HANDLE)をきちっと閉じ>たりしていますか?そうでない場合も今回のようなことが起こりえます。
ファイルを開いた状態で書込みを続けたいのですが、HANDLEをとじてしまうとその値がなくなって、処理のサイズチェックの時に動かなくなってしまっていたのでハンドルを閉じなかったのですが、いけないようですね。
No.1
- 回答日時:
CreateFileでファイルを開いたときそのハンドルは正常なもので
GetFileSizeとGetFileTimeに対してそのハンドルを
渡したときは正常動作しているということで良いですか?
で、
> 書込みのWriteFileは外部関数として私が
> 作ったものを呼び出しています。HANDLEのエラーは書込みの際起きているのですが、
> HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか。教えてください。
API の WriteFileを使わずに書き込みしているということでしょうか?
その自作しているというWriteFileでどうやってファイルを書き出しているのか
コードを見せてもらえませんか?
ご回答ありがとうございます。
助かります。
>CreateFileでファイルを開いたときそのハンドルは正常なもので
>GetFileSizeとGetFileTimeに対してそのハンドルを
>渡したときは正常動作しているということで良いですか?
はい。ハンドルの値も見ましたが値は同じでした。
出力してみましたが、時間も表示されました。
>API の WriteFileを使わずに書き込みしているということでしょうか?
>その自作しているというWriteFileでどうやってファイルを書き出しているのかコードを見せてもらえませんか?
すみません。書き方が悪かったようです。
APIのWriteFileをつかっています。同じモジュール内だと処理が多くなってしまうので、別にしてあるだけです。
メインの処理がコレです。
#include<stdio.h>
#include<winsock2.h>
#include<ws2tcpip.h>
#include<windows.h>
#include<stdlib.h>
#define BUFFER_SIZE 256
extern void HANDLE_OPEN();
char name[BUFFER_SIZE];
int main()
{
int count;
for(count=0;count<5;count++){
memset(name,0,sizeof(name));
printf("書き込みたい文字を入力して下さい\n");
scanf("%s",&name);
HANDLE_OPEN();
}
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) Windowsのマクロプログラムで、こんなことできますか? 3 2022/06/28 14:30
- Windows 10 Windows Updateが動作しません 7 2022/08/12 16:26
- Visual Basic(VBA) Excel-VBAでのファイルの開き方 4 2023/02/14 11:01
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Visual Basic(VBA) vbaエクセルマクロについて あるデータを作成し、デスクトップに.xlsx形式で保存するマクロを作成 2 2023/03/02 18:54
- UNIX・Linux VirtualBox ゲストOSにPC内蔵HDDのパーティションをマウントする方法は? 2 2023/05/06 22:52
- Visual Basic(VBA) vbaエクセルマクロについて あるデータを作成し、デスクトップに.xlsx形式で保存するマクロを作成 6 2023/03/03 18:05
- 画像編集・動画編集・音楽編集 inkscapeで作成した図の保存の仕方とその保存したファイルの編集の仕方 1 2022/09/22 09:33
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語初心者の質問失礼します。
-
csvファイルを開かずに文字を検...
-
ファイル名の先頭にアンダース...
-
HANDLE無効について
-
グローバル変数のよくない使い...
-
FileOpen 関数で既にファイル...
-
Excelマクロでの再読込み方法
-
C言語のfopenについて教えてく...
-
iniファイルについて
-
CSVファイルへの保存の際、デー...
-
大きいサイズのテキストファイ...
-
分割コンパイルの#defineについて
-
「VBScript」ADODB.Streamにお...
-
XMLファイルの表示について
-
SGファイルって何ですか?
-
Cでのネットワークファイルの読...
-
ダイアログボックスで複数フォ...
-
VBAにてEXCEL以外のファイル(テ...
-
オートキャドでCSVファイルを変...
-
DAQの出力ファイルを読み込み、...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語初心者の質問失礼します。
-
ファイル名の先頭にアンダース...
-
csvファイルを開かずに文字を検...
-
大きいサイズのテキストファイ...
-
テキストファイルの最終行を削...
-
ドラッグアンドドロップでファ...
-
分割コンパイルの#defineについて
-
バッチで118項目のCSVを処理し...
-
CSVファイルへの保存の際、デー...
-
グローバル変数のよくない使い...
-
C言語のfopenについて教えてく...
-
SGファイルって何ですか?
-
VBに、Cのincludeのようなもの...
-
ファイルの結合
-
fopenできる上限の変更
-
「VBScript」ADODB.Streamにお...
-
iniファイルに追記がしたいです。
-
XMLファイルの表示について
-
Excelマクロでの再読込み方法
-
VBAにてEXCEL以外のファイル(テ...
おすすめ情報