我是將客戶端資料一次完整接收後(並回傳訊息),再一次將寫入的資料讀出再重新編排,這必造成資料讀、寫上的時間浪費。最好方式應直接讀取記憶體中的資料排列寫入檔案,避免二次寫入,多加一次讀取的時間消耗。
另外伺服器端如何與客戶端有更直接的訊息傳送,尚有待更多的功能學習。
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerCenter extends java.lang.Thread{
private boolean OutServer = false;
private ServerSocket server; // 建立伺服器變數
private final int ServerPort = 2525; //伺服器 IP
static int peo;
public ServerCenter(){ // initial serversetting
try{
server = new ServerSocket(ServerPort); //建立伺服器物件
}
catch(java.io.IOException e){
System.out.println("伺服器啟動失敗");
}
}
public void run(){ //建立執行緒
Socket skt; // 建立伺服器動作變數
InputStream ins; //建立取得網路資料之變數
System.out.println("伺服器初始化完成");
while(!OutServer){ //當伺服器啟動時
skt = null; //伺服器動作變數清空
String ip1 = null;
for(int i=1;i<200;i++){
try{
synchronized(server){ //同步化伺服器物件
System.out.println(" 等待新客戶端呼叫 . .. ...");
skt = server.accept();} //啟動伺服器接收功能
byte buff[]=new byte[102400]; //建立接收的暫存資料空間(每次以多大的空間接受一個封包)
System.out.println("接受第 "+i+" 個連線,來自 IP = "+skt.getInetAddress()); //顯示對方 IP
if(skt.getInetAddress().toString().equals(ip1)){
i=i-1;
System.out.println("已重複連線,中斷");
skt.close();
}
ip1=skt.getInetAddress().toString();
ins = skt.getInputStream();//建立取得網路資料之物件
int n=ins.read(buff); //利用取得網資之物件來讀取記憶體暫存資料
OutputStream out=skt.getOutputStream(); //建立回應物件
String str="上傳成功!!請記得,你是第 "+i+" 位交卷!";
out.write(str.getBytes()); //回應消息
out.close(); //關閉回應
File fw= new File("C:\\PhylabTemp.txt");
BufferedWriter bfw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fw.toString(), true),"big5"));
bfw.write(new String(buff,0,n)); // 將網路暫存寫入檔案
bfw.close(); //關閉客戶端記憶體暫存資料,等一下再打開搜尋關鍵字串
ins.close(); //關閉本次接受
// System.out.println("客戶端連線結束");
FileInputStream fi = new FileInputStream("C:\\PhylabTemp.txt");
byte ba[]=new byte[fi.available()];
fi.read(ba);
int N01= new String(ba).lastIndexOf("Name:");
int N02= new String(ba).lastIndexOf(", Number:");
int N03= new String(ba).lastIndexOf(", Score:");
int N04= new String(ba).lastIndexOf("end");
// String Ns01=new Character((char)(new String(ba).charAt(N01+5))).toString();
String name = new String(ba).substring(N01+5, N02);
String number = new String(ba).substring(N02+9, N03);
String score = new String(ba).substring(N03+9, N04-1);
fi.close(); // 客戶端暫存於記憶體的資料可刪除了,因為已存到變數中
// System.out.println(" 檔案取值 成功");
FileInputStream fit=new FileInputStream("C:\\PhylabTemp.txt"); // 開新記憶體暫存檔,準備將資料寫入檔案中
FileOutputStream fot=new FileOutputStream("C:\\通訊\\"+number+"_"+name+"_"+score+".txt"); //以學號排序
FileOutputStream fot2 = null; //建立另外以上傳順序排序
if(i<10){ //為了建立 01. 02. 03...10. 11. .. 排序而定
fot2 = new FileOutputStream("C:\\通訊\\00"+i+"_"+number+"_"+name+"_"+score+".txt");
}
if(i>=10&&i<100){
fot2=new FileOutputStream("C:\\通訊\\0"+i+"_"+number+"_"+name+"_"+score+".txt");
}
if(i>=100){
fot2=new FileOutputStream("C:\\通訊\\"+i+"_"+number+"_"+name+"_"+score+".txt");
}
byte data[]=new byte[fit.available()];
fit.read(data);
fot.write(data);
fot2.write(data);
fit.close();
fot.close();
fot2.close();
// System.out.println("檔案重建成功");
skt.close(); //關閉接收功能
File df = new File("C:\\PhylabTemp.txt");
df.delete();
System.out.println("第 "+i+" 個 「"+name+"」 接收完成");
if(name.equals("close")){
System.exit(0);
}
// if(i==peoss){
// break;
// }
}
catch(java.io.IOException e){
System.out.println("連線失敗");
}
}
break;
}
}
}
4 則留言:
以上刪除部分,修改為
String instemp=new String(buff,0,n);
int N01= new String(instemp).lastIndexOf("Name:");
int N02= new String(instemp).lastIndexOf(", Number:");
int N03= new String(instemp).lastIndexOf(", Score:");
int N04= new String(instemp).lastIndexOf("end");
String name = new String(instemp).substring(N01+5, N02);
String number = new String(instemp).substring(N02+9, N03);
String score = new String(instemp).substring(N03+9, N04-1);
OutputStream out=skt.getOutputStream(); //建立回應物件
String str=name+ " 上傳成功! 你是第 "+i+" 位交卷!";
out.write(str.getBytes()); //回應消息
out.close(); //關閉回應
File fw= new File("C:\\PhylabTemp.txt");
BufferedWriter bfw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fw.toString(), true),"big5"));
bfw.write(new String(buff,0,n)); // 將網路暫存寫入檔案
bfw.close();//關閉客戶端記憶體暫存資料,等一下再打開搜尋關鍵字串
ins.close(); //關閉本次接受
利用下載到的資料,直接取得所需的變數,而不需要重新開啟檔案。可加入檔案的寫入速度並由此取值回傳給客戶端!
所以,你這是不是每加入一筆資料就會做一次排列?!
那為什麼不等所有資料都上傳完了之後再一次做排列呢?!
或是在每天的某個時段固定去跑個批次,
讓需要做排列的檔案在那個時間點一次做排列,
(例如晚上12:00server下上一次,在這同時做個批次...)
(類似銀行在某個時段會統整當天資料的概念...)
避免在server運作的同時,還要浪費資源在做檔案I/O上及排序...
事實上伺服器只要持續開著,第一個連線進來的,會給序號 1,然後 2、、、,然後利用這序號直接加在接收到的資料上。
因此,這「交卷序號」很簡單,不需等將進來的資料全下載後再排序。
另外這有個取「學號」變數(number),是另外將它資料中的學號取出來,再以此學號命名,重覆建立一個檔案。
可能我這資料還算少,所以資料一上傳,建立得很快。
你那也是個好方法,但是我就要寫另一個程式去通通重新整理一次!
收到檔案後,結果就像
http://140.121.179.194/java_01.png
上半部是用「交卷順序」建立的。
下半部是用「擷取學號」建立的。
張貼留言