天天看點

Java如何實作按指定行讀取檔案

    最近在開發實戰中,遇到了一個這樣的技術情景:

    把log4j生成的日志檔案定時刷進MySQL資料庫,比如三個小時刷一次,那麼每次刷資料的時候,如何控制檔案讀取是從上一次檔案讀取結束的地方開始繼續讀取的?并且本次要讀取到檔案結尾處。在網上各種搜尋提問後,找到了一個叫RandomAccessFile Java類解決了問題。

    先上代碼:

static int size=1;//主要是為了控制循環的次數,因為是定時刷,每次刷的檔案行數可能不一樣
	static long chars=0;//chars指的是字元數
	/**
	 * 讀取檔案内容
	 * @param fileName
	 */
	  public Map readANDwrite(String fileName) {
	    	
	    	//大集合,以sessionid為鍵,以一次session的所有通路記錄list為值進行存儲
	    	Map<String,Map> bigMap = new HashMap();
	    	
	    	//一次session的通路記錄集合
	        File file = new File(fileName);
	        
	        //java提供的一個可以分頁讀取檔案的類,此類的執行個體支援對随機通路檔案的讀取和寫入
	        RandomAccessFile rf = null;
	        
	        String tempString = null;
	        try {
	            
	                //初始化RandomAccessFile,參數一個為檔案路徑,一個為權限設定,這點與Linux類似,r為讀,w為寫
	    		rf = new RandomAccessFile(fileName, "rw");
	    		
	    		//設定到此檔案開頭測量到的檔案指針偏移量,在該位置發生下一個讀取或寫入操作
	    		rf.seek(chars);
	    		
	    		//擷取檔案的行數
	    		int fileSize = getTotalLines(file);
	    	        for (int i = size-1; i < fileSize; i++) {//從上一次讀取結束時的檔案行數到本次讀取檔案時的總行數中間的這個差數就是循環次數
	    			
	    			//一行一行讀取
	    			tempString = rf.readLine();
	    			//檔案中文亂碼處理
	    			tempString = tempString.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
	    			tempString = tempString.replaceAll("\\+", "%2B");
	    			tempString = java.net.URLDecoder.decode(tempString, "GB2312");
	    		
	    			//将字元串JSON轉換為實體JSON,以便能通過key取value
	    			JSONObject json = JSONObject.fromObject(tempString);
					String refPage = json.get("refPage").toString();
					System.out.println(refPage);
					Map tmap = new HashMap();

					if (bigMap.containsKey(refPage))
						tmap = (Map) bigMap.get(refPage);
					else {
						tmap = new HashMap();
					}
					// 計數
					String tCount = "count";
					int pvCount = 1;
					if (tmap.containsKey(tCount)) {
						pvCount = (Integer) tmap.get(tCount);
					}
					pvCount++;
					tmap.put(tCount, pvCount);
					bigMap.put(refPage, tmap);
	    		}
	    		//傳回此檔案中的目前偏移量。 
	    		chars = rf.getFilePointer();
	    		size=fileSize;
			} catch (IOException e) {
				e.printStackTrace();
			}catch(JSONException j){
				
			} finally {
				if (rf != null) {
					try {
						rf.close();
					} catch (IOException e1) {
					}
				}
			}
	        return bigMap;
	    }
           
 //擷取檔案的行數
	  static int getTotalLines(File file) throws IOException {
	        FileReader in = new FileReader(file);
	        LineNumberReader reader = new LineNumberReader(in);
	        String s = reader.readLine();
	        int lines = 0;
	        while (s != null) {
	            lines++;
	            s = reader.readLine();
	        }
	        reader.close();
	        in.close();
	        return lines;
	    }