
UserModeLinuxを起動する際のルートファイルシステム(4294971392バイト)
をサーバ側からクライアント側に転送したいと考えています。
以下のプログラムを実行した結果、エラーが出てしまいます。
容量が大きなファイルのため、出てきてしまうエラーだと思うのですが。
またおかしなことに、エラーが出るのでプログラムを停止して
クライアント側のディレクトリを確認すると
ルートファイルシステムが存在し、UserModeLinuxを起動することもできました。しかしコンソールにはエラーが表示されるので困っています。
このような場合にどのように対処するべきでしょうか。
サーバ側
import java.net.*;
import java.io.*;
public class FileTransferServerroot {
public static void main(String[] args) throws IOException{
if (args.length != 2)
throw new IllegalArgumentException("Arguments should be host,port and filepath");
int serverPort = Integer.parseInt(args[0]);
String filename = args[1];
byte[] data = new byte[32];
//ソケットの作成
ServerSocket socket = new ServerSocket(serverPort);
Socket sock = socket.accept();
System.out.println("Connected to server");
//ストリームの作成
FileInputStream fin = new FileInputStream(filename);
OutputStream out = sock.getOutputStream();
//ファイルの内容を読み出し、送信する
System.out.println("Sending file : " + filename);
int totalSize = 0;
int len = 0;
for(;;){
len = fin.read(data);
totalSize += len;
out.write(data, 0, len);
if(totalSize == 4294971392L)
break;
}
fin.close();
fin = null;
System.out.println("linux.umlを送信完了しました");
socket.close();
}
}
クライアント側
import java.net.*;
import java.io.*;
public class FileTransferClientroot {
public static void main(String[] args) throws IOException{
if (args.length != 3)
throw new IllegalArgumentException("An argument should be port and filename");
String host = args[0];
int servPort = Integer.parseInt(args[1]);
String filename = args[2];
System.out.println("Output file name : " + filename);
//Create FileOutputStream
FileOutputStream fout = new FileOutputStream(filename);
//Create ServerSocket
Socket servSock = new Socket(host, servPort);
int recvMsgSize;
int bufSize = 32;
System.out.println("Size of ReceiveBuffer : " + bufSize);
byte[] byteBuffer = new byte[bufSize];
//Create InputStream
InputStream in = servSock.getInputStream();
//Read message and print it out
int totalByte = 0;
//while((recvMsgSize = in.read(byteBuffer)) != -1){
for(;;){
recvMsgSize = in.read(byteBuffer);
totalByte += recvMsgSize;
fout.write(byteBuffer,0,recvMsgSize);
if(totalByte == 4294971392L)
break;
}
System.out.println("linux.umlを受信完了しました");
servSock.close();
fout.close();
fout = null;
}
}
実行結果(サーバ側)
Connected to server
Sending file : uml-root-hardy
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
at FileTransferServerroot.main(FileTransferServerroot.java:25)
実行結果(クライアント側)
Output file name : uml-root-hardy
Size of ReceiveBuffer : 32
Exception in thread "main" java.lang.IndexOutOfBoundsException
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(Unknown Source)
at FileTransferClientroot.main(FileTransferClientroot.java:28)

No.6ベストアンサー
- 回答日時:
> -1を返すというのはソケットを閉じていますよね。
> できればソケットを閉じずに2つのファイルを転送したいと考えているのですが。
やっぱり勘違いしていましたか。
ストリームが最後に達しただけでTCP/IPのセッションは閉じませんよ。
そもそも、最初のコードで
if(totalByte == 4294971392L) break;
これが機能しないのは、通信中に recvMsgSize = -1 が発生し totalByte が期待通りの値にならなくなるからです。
>>out は BufferedOutputStream で宣言
>>in は BufferedInputStream で宣言
>それぞれどのように宣言すればよいでしょうか。
まずはマニュアルを見る癖をつけてください。
http://java.sun.com/javase/ja/6/docs/ja/api/java …
http://java.sun.com/javase/ja/6/docs/ja/api/java …
BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream());
BufferedInputStream in = new BufferedInputStream(servSock.getInputStream())
ですよ。

No.5
- 回答日時:
> どのように対処すればエラーなく動作するでしょうか。
以下のように変更します。
totalSize はループ以降で使用されないので削除しました。
サーバー側
------------
for(;;){
len = fin.read(data);
totalSize += len;
out.write(data, 0, len);
if(totalSize == 4294971392L)
break;
}
------------
↓
out は BufferedOutputStream で宣言
OutputStream ではディスクI/Oの影響を直接受けるため、Buffered で安定的に送信する。
------------
while((len = fin.read(data) != -1){
out.write(data, 0, len);
}
out.flush();
------------
クライアント側
------------
//while((recvMsgSize = in.read(byteBuffer)) != -1){
for(;;){
recvMsgSize = in.read(byteBuffer);
totalByte += recvMsgSize;
fout.write(byteBuffer,0,recvMsgSize);
if(totalByte == 4294971392L)
break;
}
------------
↓
in は BufferedInputStream で宣言
InputStream で宣言すると、ループが速すぎて受信完了前に -1 になることがあるため
------------
while((recvMsgSize = in.read(byteBuffer)) != -1){
fout.write(byteBuffer,0,recvMsgSize);
}
------------
この回答への補足
-1を返すというのはソケットを閉じていますよね。
できればソケットを閉じずに2つのファイルを転送したいと考えているのですが。
fout.close();
fout = null;
と行うのは、ソケットも閉じてしまいますか?
また
>out は BufferedOutputStream で宣言
>in は BufferedInputStream で宣言
それぞれどのように宣言すればよいでしょうか。
どうしてもうまくいかないのですが。
No.4
- 回答日時:
失礼
>UserModeLinuxを起動する際のルートファイルシステム(4294971392バイト)
読み飛ばしていました。!!!
No3は、忘れてください。
ただ逆に、4294971392この数字にこだわる必要が
ないのでは??
なんで、質問プログラムの注釈文にあるように
>//while((recvMsgSize = in.read(byteBuffer)) != -1){
この方法を避けたのですか??
この回答への補足
お返事ありがとうございます。
この数字はプロパティから確認したため、そうしました。
ソケットを閉じるのを避けたのは、
このファイル転送プログラムは大きなプログラムの一部分で
ソケットを閉じたり開いたりするのをしないように
指示を受けているからです。
No.3
- 回答日時:
質問プログラムとNo2さんの回答を見ると
答えが、すでに出ているような気もするのですが。
私の勘違いかな???
別な視点で、疑問点!!!
>if(totalByte == 4294971392L)
この数字、4294971392Lは、何処まで、正確なのですか
このif文、1でも、ずれると、無限ループに
陥りますが。
No2さんも、書いているように、
totalByte == 4294971392Lをtrueにするのは、
かなりの至難のわざのようなきもするのですが。。
もともと、大きな数字ですし。
ちなみに、もともとのデータが、 4294971392Lより大きく
4294971392Lで切りたいなら、また、工夫が必要ですが、
大体 4294971392Lの付近でデータを切っていいなら、
if(totalByte >= 4294971392L)
これなら、無限ループには、ならないのでは???
また、もともとのデータが、4294971392Lより小さいと
この評価の前に、エラーが出ますが。
もともと、データどういうものか解らないので、
この辺で、

No.2
- 回答日時:
int totalSize = 0;
これを
long totalSize = 0;
で解決します。
もっときれいに書くのでしたら、ファイルを read で読み取った時点で判別したほうが良いでしょう。
現在の状態ですと、
if(totalByte == 4294971392L)
は常にfalseになるため、ファイルの最後その次のループで
len = -1
recvMsgSize = -1
が入ります。その後、サーバー、クライアント
25: out.write(data, 0, len);
28: fout.write(byteBuffer,0,recvMsgSize);
でArrayIndexOutOfBoundsExceptionが発生し、停止します。
この回答への補足
お返事ありがとうございます。
longtotalSize=0;
とすることでその部分は解決しました。
もう一つの方ですが
if(totalByte == 4294971392L)
としてもご指摘どおり
サーバ側でArrayIndexOutOfBoundsException
クライアント側でjava.lang.IndexOutOfBoundsException
のエラーが出てしまいます。
どのように対処すればエラーなく動作するでしょうか。
教えてください。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Java 直し方について教えて頂きたいです。 4 2022/08/13 02:11
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- C言語・C++・C# 大量のデータを読み込んで表示する速度を改善したい 8 2023/05/07 13:29
- Java java final 1 2022/06/10 22:49
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
九九を横に表示する。
-
テキストファイルから空白行をよむ
-
JAVAでエラーがでる。
-
yyyymmddからyyyy/mm/d...
-
equalsの逆
-
大きな容量のファイルを転送する
-
テキストファイルにおいて任意...
-
BufferedReader.readline()で読...
-
eclipseでmysqlからテーブル情...
-
linuxでapache poiが動かない。
-
System.err. printlnとSystem.o...
-
C言語のポインターに関する警告
-
1~100までの数字を表示したい
-
ORA-01858: 数値を指定する箇所...
-
Javaで文字と数字が混ざったも...
-
一定のスペースを空けて端を揃...
-
動的配列が存在(要素が有る)か...
-
Javaで改行などが出来ないのです。
-
変数を動的に利用するには?
-
IF関数でEmpty値を設定する方法。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
yyyymmddからyyyy/mm/d...
-
テキストファイルから空白行をよむ
-
csv出力について
-
InputStream.read()でタイムア...
-
Java int sum = 0は必要ですか?
-
FileクラスのcanRead/canWrite...
-
Class.forNameでエラーになる
-
BufferedReaderでのエラー
-
equalsの逆
-
Javaでデータに登録する度にID...
-
ProcessBuilderを使用して、対...
-
テキストファイルの任意の文字...
-
Javaの質問です。テキストファ...
-
JAVAでエラーがでる。
-
java連結
-
[JAVA]エラーが解決できません。
-
九九を横に表示する。
-
javaからffmpegの利用
-
Java FileDialog に関して
-
JavamailでGmailのお気に入りフ...
おすすめ情報