導航:首頁 > 源碼編譯 > getchannel源碼解析

getchannel源碼解析

發布時間:2022-09-08 11:42:41

❶ netty3.6.2中寫數據的過程,以及寫數據寫不出去後怎麼處理

netty寫數據的時候,會先放到一個緩存隊列AbstractNioChannel.writeBufferQueue中,這個隊列是WriteRequestQueue
java代碼
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
……
} else if (e instanceof MessageEvent) {
MessageEvent event = (MessageEvent) e;
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
boolean offered = channel.writeBufferQueue.offer(event);//寫到channel的writeBufferQueue
assert offered;
channel.worker.writeFromUserCode(channel);
}
}
WriteRequestQueue的offer方法中會根據緩存消息的總大小(位元組數)判斷是否超過了高水位線highWaterMark,如果第一次超過了超過高水位線,就會fireChannelInterestChanged;後邊如果仍然一直往隊列放數據,緩存的消息的大小持續超過高水位線的時候,不會再fireChannelInterestChanged。
Java代碼
public boolean offer(MessageEvent e) {
boolean success = queue.offer(e);
assert success;

int messageSize = getMessageSize(e);
int newWriteBufferSize = writeBufferSize.addAndGet(messageSize);
int highWaterMark = getConfig().getWriteBufferHighWaterMark();

if (newWriteBufferSize >= highWaterMark) {
if (newWriteBufferSize - messageSize < highWaterMark) {
highWaterMarkCounter.incrementAndGet();
if (!notifying.get()) {
notifying.set(Boolean.TRUE);
fireChannelInterestChanged(AbstractNioChannel.this);
notifying.set(Boolean.FALSE);
}
}
}
return true;
}
fireChannelInterestChanged這個會調到SimpleChannelUpstreamHandler.handleUpstream,觸發SimpleChannelUpstreamHandler.channelInterestChanged,可以通過繼承這個方法來自定義做些事情。高水位的值可以通過Bootstrap設置,最終會調到DefaultNioSocketChannelConfig.setOption。writeBufferHighWaterMark默認值為64K
Java代碼
public boolean setOption(String key, Object value) {
if (super.setOption(key, value)) {
return true;
}
if ("writeBufferHighWaterMark".equals(key)) {
setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
} else if ("writeBufferLowWaterMark".equals(key)) {
setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
} else if ("writeSpinCount".equals(key)) {
setWriteSpinCount(ConversionUtil.toInt(value));
} else if ("".equals(key)) {
(() value);
} else if ("receiveBufferSizePredictor".equals(key)) {
setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
} else {
return false;
}
return true;
}
然後在write0的時候會從隊列拉數據,拉數據的時候,如果發現本次拉的數據會導致緩存的數據大小(位元組)從低水位writeBufferLowWaterMark之上,掉到了低水位之下,即跨過了低水位,會再次觸發fireChannelInterestChanged事件。writeBufferLowWaterMark默認值為32K
Java代碼
public MessageEvent poll() {
MessageEvent e = queue.poll();
if (e != null) {
int messageSize = getMessageSize(e);
int newWriteBufferSize = writeBufferSize.addAndGet(-messageSize);
int lowWaterMark = getConfig().getWriteBufferLowWaterMark();


if (newWriteBufferSize == 0 || newWriteBufferSize < lowWaterMark) {
if (newWriteBufferSize + messageSize >= lowWaterMark) {//本次拉取,是的緩存數據大小掉到了低水位之下
highWaterMarkCounter.decrementAndGet();
if (isConnected() && !notifying.get()) {
notifying.set(Boolean.TRUE);
fireChannelInterestChanged(AbstractNioChannel.this);
notifying.set(Boolean.FALSE);
}
}
}
}
return e;
}
超過高水位和低於低水位都會觸發fireChannelInterestChanged,怎麼區分呢?通過AbstractChannel. isWritable(),如果channel的interestOps里邊有注冊過OP_WRITE,則是不可寫的,否則是可寫的
Java代碼
public boolean isWritable() {
return (getInterestOps() & OP_WRITE) == 0;
}
public int getInterestOps() {
if (!isOpen()) {
return Channel.OP_WRITE;
}

int interestOps = getRawInterestOps();
int writeBufferSize = this.writeBufferSize.get();
if (writeBufferSize != 0) {
if (highWaterMarkCounter.get() > 0) {//還記得這個值,放數據到發送隊列的時候值+=1,從隊列拉數據出來的時候值-=1
int lowWaterMark = getConfig().getWriteBufferLowWaterMark();
if (writeBufferSize >= lowWaterMark) {//緩存隊列數據量,超過高水位,也超過了低水位,意味著高水位>低水位,此時等於注冊寫操作
interestOps |= Channel.OP_WRITE;
} else {
interestOps &= ~Channel.OP_WRITE;//緩存隊列數據量,超過高水位但是低於低水位,意味著低水位>高水位,此時等於沒有注冊寫操作
}
} else {//超過高水位counter<=0,意味著當前數據量小於高水位
int highWaterMark = getConfig().getWriteBufferHighWaterMark();
if (writeBufferSize >= highWaterMark) {//這里,緩存數據量仍然高於高水位.....並發?按道理說channel的處理是單線程處理的,此時等於注冊寫操作
interestOps |= Channel.OP_WRITE;
} else {
interestOps &= ~Channel.OP_WRITE;
}
}
} else {
interestOps &= ~Channel.OP_WRITE;//寫隊列沒數據,沒有注冊寫操作
}

return interestOps;
}
即,如果超過高水位isWritable()==false,低於低水位isWritable()==true,低水位優先順序高於高水位,即如果 當前水位>低水位 則不可寫,否則可寫

如果在通過netty向某機器寫數據,但是寫很緩慢,則會導致數據都緩存到netty的發送隊列中,如果不做控制,可能會導致full gc/cms gc頻繁,甚至最終OOM。所以可以考慮用高水位和低水位的值來控制netty的緩存隊列,即用AbstractChannel.isWritable來控制是否繼續寫,如果AbstractChannel.isWritable==false,則丟棄數據,或者記錄發送數據的狀態,待後續緩存數據隊列水位下降到安全水位後再發送。

❷ 用java實現pdf轉jpg圖片的全代碼,我這里附上參考代碼。

學JAVA就到廣州瘋狂JAVA來學習 李剛授課 我是不能。。。

❸ 做seo懂代碼還是很好的,分享一點關於KesionCMS的調用代碼

======網站通用標簽==============
{$GetSiteTitle} 顯示網站標題
{$GetSiteName} 顯示網站名稱
{$GetSiteLogo} 顯示網站logo(不帶參數)
{=GetLogo(130,90)} 顯示網站logo(帶參數,logo的寬和高)
{=GetTags(1,10)}熱門Tags
{=GetTags(2,10)}訪問時間排序
{=GetTags(3,10)}添加時間排序
{$GetSiteCountAll}顯示網站信息統計(欄目總數,文章總數….)
{$GetSiteOnline}顯示在線人數(總在線:X人 用戶:X人; 遊客:X人)
{=GetTopUser(5,more...)}顯示活躍用戶排行5條
{=GetUserDynamic(10)}顯示用戶動態(大家都在做什麼)最近更新前10條
{$GetSpecial}顯示專題入口
{$GetFriendLink}顯示友情鏈接入口
{$GetSiteUrl}顯示網站URL
{#GetFullDomain}顯示網站完整URL(不管有沒有啟用相對路徑,始終返回完整域名) ---- NEW
{$GetInstallDir}顯示網站安裝路徑
{$GetManageLogin}顯示管理入口
{$GetCopyRight}顯示版權信息
{$GetMetaKeyWord}顯示針對搜索引擎的關鍵字
{$GetMetaDescript}顯示針對搜索引擎的描述
{$GetWebmaster}顯示站長
{$GetWebmasterEmail}顯示站長Email
{$GetClubInstallDir} 論壇安裝目錄
{$TodayGroupbuyLink}獲得今日團購URL
{$HistoryGroupbuyLink}獲得往期團購URL
{$GetTemplateDir}模板路徑
{$GetCssDir}CSS路徑
=====常用腳本特效標簽=========
{=JS_Ad("左聯Flash地址","右聯Flash地址","/images/close.gif",0.8)} 對聯廣告
{$JS_Time1}時間特效(樣式:2006年4月8日)
{$JS_Time2}時間特效(樣式:2006年4-月8日 星期六)
{$JS_Time3}時間特效(樣式:2007年6月1日 星期五 [農歷 4月初五])
{$JS_Time4}時間特效(樣式:2006年4月8日 11:50:46 星期六)
{$JS_Language}簡繁轉換
{$JS_HomePage}設為首頁
{$JS_Collection}加入收藏
{$JS_ContactWebMaster}聯系站長
{$JS_GoBack}返回上一頁
{$JS_WindowClose}關閉窗口
{$JS_NoSave}頁面不被別人」另存為」
{$JS_NoIframe}頁面不被別人放到框架中
{$JS_NoCopy}防止網頁信息被復制
{$JS_DCRoll}雙擊滾屏特效
{=JS_Status1("請在這里輸入要顯示的文字",120)} 狀態欄打字效果
{=JS_Status2("請在這里輸入要顯示的文字",120)} 文字在狀態欄上從右往左循環顯示效果
{=JS_Status3("請在這里輸入要顯示的文字",150)} 文字在狀態欄上打字之後移動消失效果
==========系統函數標簽(KesionCMS入門標簽)=============
系統函數標簽是用戶自己在後台標簽管理系統函數標簽裡面創建的標簽,標簽名稱由自己命名。
調用方式{LB_標簽名稱};
常用標簽如下所示:
{LB_頻道導航} {LB_網站公告} {LB_友情鏈接} {LB_位置導航} {LB_相關文章} {LB_終級文章列表}
=============會員系統專用標簽=================
{$GetUserLoginByScript}顯示會員登錄入口(Script調用)
{$GetPopLogin}顯示會員登錄入口(跳窗)
{$GetTopUserLogin} 顯示會員登錄入口(橫排)
{$GetUserLogin}顯示會員登錄入口(豎排)
{$GetAllUserList}顯示所有注冊會員列表(僅限使用於會員列表頁模板)
{$GetUserRegLicense}顯示新會員注冊服務條款和聲明
{$Show_UserNameLimitChar}顯示新會員注冊時用戶名最少字元數
{$Show_UserNameMaxChar}顯示新會員注冊時用戶名最多字元數
{$Show_VerifyCode}顯示新會員注冊時驗證碼
{$GetUserRegResult}新會員注冊成功信息
=============搜索專用標簽==============
{$GetSearchByDate} 高級日歷搜索(小插件)
{$GetSearch} 總站搜索
{$GetArticleSearch}文章系統搜索
{$GetPhotoSearch}圖片系統搜索
{$GetDownLoadSearch}下載系統搜索
{$GetFlashSearch}動漫系統搜索
{$GetShopSearch}商城系統搜索
{$GetMovieSearch}影視系統搜索
{$GetSupplySearch}供求系統搜索
{$GetesfSearch}二手房源搜索
{$GetzfSearch}出租房源搜索
===========頻道(欄目)專用標簽===============
{$GetChannelID} 顯示當前模型ID
{$GetChannelName}顯示當前模型名稱
{$GetItemName}顯示當前模型的項目名稱
{$GetItemUnit}顯示當前模型的項目單位
{$GetClassID}顯示當前欄目ID
{$GetClassName}顯示當前欄目名稱
{$GetClassUrl}顯示當前欄目鏈接地址
{$GetClassPic}顯示當前欄目圖片
{$GetClassIntro}顯示當前欄目介紹
{$GetClass_Meta_KeyWord}針對搜索引擎的關鍵字
{$GetClass_Meta_Description}針對搜索引擎的描述
{$GetParentID}顯示父欄目ID
{$GetParentUrl}顯示父欄目鏈接地址
{$GetParentClassName}顯示父欄目名稱
======================================內容頁標簽====================================
==========文章內容頁標簽(以下標簽僅適用於文章內容頁)=============
{$GetArticleUrl} 當前文章URL
{$ChannelID}當前模型ID
{$InfoID}當前文章小ID
{$ItemName}當前項目名稱
{$ItemUnit}當前項目單位
{$GetArticleShortTitle}文章簡短標題
{=GetPhoto(130,90)}內容頁圖片(寬*高)
{$GetArticleTitle}完整標題
{$GetArticleKeyWord}關鍵字Tags
{$GetKeyTags}取得文章Tags
{$GetArticleIntro}文章導讀
{$GetArticleContent}文章內容
{$GetArticleAuthor}文章作者
{$GetArticleOrigin}文章來源
{$GetArticleDate}添加日期(格式:2009年5月1日)
{$GetDate} 添加日期(直接輸出)
{$GetHits}文章人氣(總瀏覽數)
{$GetHitsByDay}文章本日瀏覽數
{$GetHitsByWeek}文章本周瀏覽數
{$GetHitsByMonth}文章本月瀏覽數
{$GetArticleInput}文章錄入(帶鏈接)
{$GetUserName}文章錄入(不帶鏈接)
{$GetRank}文章推薦等級
{$GetArticleProperty}顯示文章的屬性(熱門、推薦、滾動…)
{$GetArticleSize}顯示文章[字體:大 中 小]
{$GetArticleAction}顯示[發表評論] [告訴好友] [列印文章]
{$GetPrevArticle}顯示上一篇文章
{$GetNextArticle}顯示下一篇文章
{$GetPrevUrl}顯示上一篇文章URL
{$GetNextUrl}顯示下一篇文章URL
{$GetShowComment}顯示評論
{$GetWriteComment}發表評論

❹ {$Field(1,GetChannel,3)}

獲取欄位的,具體獲得什麼不知道,不知道你這個從哪讀的數據源

❺ java中getchannel的含義和具體用法。

getChannel()是得到FileChannel類的一種方法,只有FileInputStream/FileOutputStream/RandomAccessFile對象有getChannel()方法;
比如:FileChannel fc = new FileOutputStream("data.txt").getChannel();

❻ 怎麼將一個channel的數據發送給另一個channel

5.不同通道channel之間傳輸數據

在Java的NIO中,如果兩個通道中有一個是FileChannel,那麼我們可以直接將數據從一個channel傳輸到另外一個channel中。兩個通道之間傳輸數據的方式有兩種,分別是:
- transferFrom()
- transferTo()

5.1 transferFrom()

FileChannel 的transferFrom()方法可以將數據從源通道傳輸到FileChannel中(這個方法在JDK文檔中解釋為將位元組從給定的可讀取位元組通道傳輸到此通道的文件中)。下面是一個簡單的例子:

RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");
FileChannel fromChannel = fromFile.getChannel();//獲取source的通道;

RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");
FileChannel toChannel = toFile.getChannel();//獲取dest的通道;

long position = 0;
long count = fromChannel.size();

long result = toChannel.transferFrom(fromChannel, position, count);

LogUtil.log_debug(""+result);
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
方法的輸入參數
- position表示從position處開始向目標文件寫入數據,
- count表示最多傳輸的位元組數。如果源通道的剩餘空間小於count個位元組,則所傳輸的位元組數要小於請求的位元組數。

此外要注意,在SoketChannel的實現中,SocketChannel只會傳輸此刻准備好的數據(可能不足count位元組)。因此,SocketChannel可能不會將請求的所有數據(count個位元組)全部傳輸到FileChannel中。

5.2 transferTo()方法

transferTo()方法將數據從FileChannel傳輸到其他的channel中。下面是一個簡單的例子:

RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");
FileChannel fromChannel = fromFile.getChannel();//獲取source的通道;

RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");
FileChannel toChannel = toFile.getChannel();//獲取dest的通道;

long position = 0;
long count = fromChannel.size();
long result = fromChannel.transferTo(position, count, toChannel);
LogUtil.log_debug(""+result);
1
2
3
4
5
6
7
8
9
10

1
2
3
4
5
6
7
8
9
10
觀察一下就可以發現,其實這兩個例子其實非常的相似,如果僅僅從文件IO的角度來看,就是兩個文件之間的數據復制;

上面所說的關於SocketChannel的問題在transferTo()方法中同樣存在。SocketChannel會一直傳輸數據直到目標buffer被填滿。

❼ channelhandlercontext getchannel.getid;在哪個jar包裡面

1、Client向Server發送http請求。 2、Server端對http請求進行解析。 3、Server端向client發送http響應。 4、Client對http響應進行解析。

❽ Android socket源碼解析(三)socket的connect源碼解析

上一篇文章著重的聊了socket服務端的bind,listen,accpet的邏輯。本文來著重聊聊connect都做了什麼?

如果遇到什麼問題,可以來本文 https://www.jianshu.com/p/da6089fdcfe1 下討論

當服務端一切都准備好了。客戶端就會嘗試的通過 connect 系統調用,嘗試的和服務端建立遠程連接。

首先校驗當前socket中是否有正確的目標地址。然後獲取IP地址和埠調用 connectToAddress 。

在這個方法中,能看到有一個 NetHooks 跟蹤socket的調用,也能看到 BlockGuard 跟蹤了socket的connect調用。因此可以hook這兩個地方跟蹤socket,不過很少用就是了。

核心方法是 socketConnect 方法,這個方法就是調用 IoBridge.connect 方法。同理也會調用到jni中。

能看到也是調用了 connect 系統調用。

文件:/ net / ipv4 / af_inet.c

在這個方法中做的事情如下:

注意 sk_prot 所指向的方法是, tcp_prot 中 connect 所指向的方法,也就是指 tcp_v4_connect .

文件:/ net / ipv4 / tcp_ipv4.c

本質上核心任務有三件:

想要能夠理解下文內容,先要明白什麼是路由表。

路由表分為兩大類:

每個路由器都有一個路由表(RIB)和轉發表 (fib表),路由表用於決策路由,轉發表決策轉發分組。下文會接觸到這兩種表。

這兩個表有什麼區別呢?

網上雖然給了如下的定義:

但實際上在Linux 3.8.1中並沒有明確的區分。整個路由相關的邏輯都是使用了fib轉發表承擔的。

先來看看幾個和FIB轉發表相關的核心結構體:

熟悉Linux命令朋友一定就能認出這裡面大部分的欄位都可以通過route命令查找到。

命令執行結果如下:

在這route命令結果的欄位實際上都對應上了結構體中的欄位含義:

知道路由表的的內容後。再來FIB轉發表的內容。實際上從下面的源碼其實可以得知,路由表的獲取,實際上是先從fib轉發表的路由字典樹獲取到後在同感加工獲得路由表對象。

轉發表的內容就更加簡單

還記得在之前總結的ip地址的結構嗎?

需要進行一次tcp的通信,意味著需要把ip報文准備好。因此需要決定源ip地址和目標IP地址。目標ip地址在之前通過netd查詢到了,此時需要得到本地發送的源ip地址。

然而在實際情況下,往往是面對如下這么情況:公網一個對外的ip地址,而內網會被映射成多個不同內網的ip地址。而這個過程就是通過DDNS動態的在內存中進行更新。

因此 ip_route_connect 實際上就是選擇一個緩存好的,通過DDNS設置好的內網ip地址並找到作為結果返回,將會在之後發送包的時候填入這些存在結果信息。而查詢內網ip地址的過程,可以成為RTNetLink。

在Linux中有一個常用的命令 ifconfig 也可以實現類似增加一個內網ip地址的功能:

比如說為網卡eth0增加一個IPV6的地址。而這個過程實際上就是調用了devinet內核模塊設定好的添加新ip地址方式,並在回調中把該ip地址刷新到內存中。

注意 devinet 和 RTNetLink 嚴格來說不是一個存在同一個模塊。雖然都是使用 rtnl_register 注冊方法到rtnl模塊中:

文件:/ net / ipv4 / devinet.c

文件:/ net / ipv4 / route.c

實際上整個route模塊,是跟著ipv4 內核模塊一起初始化好的。能看到其中就根據不同的rtnl操作符號注冊了對應不同的方法。

整個DDNS的工作流程大體如下:

當然,在tcp三次握手執行之前,需要得到當前的源地址,那麼就需要通過rtnl進行查詢內存中分配的ip。

文件:/ include / net / route.h

這個方法核心就是 __ip_route_output_key .當目的地址或者源地址有其一為空,則會調用 __ip_route_output_key 填充ip地址。目的地址為空說明可能是在回環鏈路中通信,如果源地址為空,那個說明可能往目的地址通信需要填充本地被DDNS分配好的內網地址。

在這個方法中核心還是調用了 flowi4_init_output 進行flowi4結構體的初始化。

文件:/ include / net / flow.h

能看到這個過程把數據中的源地址,目的地址,源地址埠和目的地址埠,協議類型等數據給記錄下來,之後內網ip地址的查詢與更新就會頻繁的和這個結構體進行交互。

能看到實際上 flowi4 是一個用於承載數據的臨時結構體,包含了本次路由操作需要的數據。

執行的事務如下:

想要弄清楚ip路由表的核心邏輯,必須明白路由表的幾個核心的數據結構。當然網上搜索到的和本文很可能大為不同。本文是基於LInux 內核3.1.8.之後的設計幾乎都沿用這一套。

而內核將路由表進行大規模的重新設計,很大一部分的原因是網路環境日益龐大且復雜。需要全新的方式進行優化管理系統中的路由表。

下面是fib_table 路由表所涉及的數據結構:

依次從最外層的結構體介紹:

能看到路由表的存儲實際上通過字典樹的數據結構壓縮實現的。但是和常見的字典樹有點區別,這種特殊的字典樹稱為LC-trie 快速路由查找演算法

這一篇文章對於快速路由查找演算法的理解寫的很不錯: https://blog.csdn.net/dog250/article/details/6596046

首先理解字典樹:字典樹簡單的來說,就是把一串數據化為二進制格式,根據左0,右1的方式構成的。

如圖下所示:

這個過程用圖來展示,就是沿著字典樹路徑不斷向下讀,比如依次讀取abd節點就能得到00這個數字。依次讀取abeh就能得到010這個數字。

說到底這種方式只是存儲數據的一種方式。而使用數的好處就能很輕易的找到公共前綴,在字典樹中找到公共最大子樹,也就找到了公共前綴。

而LC-trie 則是在這之上做了壓縮優化處理,想要理解這個演算法,必須要明白在 tnode 中存在兩個十分核心的數據:

這負責什麼事情呢?下面就簡單說說整個lc-trie的演算法就能明白了。

當然先來看看方法 __ip_dev_find 是如何查找

文件:/ net / ipv4 / fib_trie.c

整個方法就是通過 tkey_extract_bits 生成tnode中對應的葉子節點所在index,從而通過 tnode_get_child_rcu 拿到tnode節點中index所對應的數組中獲取葉下一級別的tnode或者葉子結點。

其中查找index最為核心方法如上,這個過程,先通過key左移動pos個位,再向右邊移動(32 - bits)演算法找到對應index。

在這里能對路由壓縮演算法有一定的理解即可,本文重點不在這里。當從路由樹中找到了結果就返回 fib_result 結構體。

查詢的結果最為核心的就是 fib_table 路由表,存儲了真正的路由轉發信息

文件:/ net / ipv4 / route.c

這個方法做的事情很簡單,本質上就是想要找到這個路由的下一跳是哪裡?

在這裡面有一個核心的結構體名為 fib_nh_exception 。這個是指fib表中去往目的地址情況下最理想的下一跳的地址。

而這個結構體在上一個方法通過 find_exception 獲得.遍歷從 fib_result 獲取到 fib_nh 結構體中的 nh_exceptions 鏈表。從這鏈表中找到一模一樣的目的地址並返回得到的。

文件:/ net / ipv4 / tcp_output.c

❾ 利用java.nio的FileChannel能夠實現按行讀取文件嗎(解決了)

利用java.nio的FileChannel能夠實現按行讀取文件:

具體思路是:設置兩個緩沖區,一大一小,大的緩沖區為每次讀取的量,小的緩沖區存放每行的數據(確保大小可存放文本中最長的那行)。讀取的時候判斷是不是換行符13,是的話則返回一行數據,不是的話繼續讀取,直到讀完文件。

實現方法:

FileChannelfc=raf.getChannel();
//一次讀取文件,讀取的位元組緩存數
ByteBufferfbb=ByteBuffer.allocate(1024*5);
fc.read(fbb);
fbb.flip();
//每行緩存的位元組根據你的實際需求
ByteBufferbb=ByteBuffer.allocate(500);

//判斷是否讀完文件
publicbooleanhasNext()throwsIOException{

if(EOF)returnfalse;
if(fbb.position()==fbb.limit()){//判斷當前位置是否到了緩沖區的限制
if(readByte()==0)returnfalse;
}
while(true){
if(fbb.position()==fbb.limit()){
if(readByte()==0)break;
}
bytea=fbb.get();
if(a==13){
if(fbb.position()==fbb.limit()){
if(readByte()==0)break;
}
returntrue;
}else{
if(bb.position()<bb.limit()){
bb.put(a);
}else{
if(readByte()==0)break;
}
}
}
returntrue;
}
閱讀全文

與getchannel源碼解析相關的資料

熱點內容
卡爾曼濾波演算法書籍 瀏覽:768
安卓手機怎麼用愛思助手傳文件進蘋果手機上 瀏覽:843
安卓怎麼下載60秒生存 瀏覽:802
外向式文件夾 瀏覽:235
dospdf 瀏覽:430
怎麼修改騰訊雲伺服器ip 瀏覽:387
pdftoeps 瀏覽:492
為什麼鴻蒙那麼像安卓 瀏覽:735
安卓手機怎麼拍自媒體視頻 瀏覽:185
單片機各個中斷的初始化 瀏覽:723
python怎麼集合元素 瀏覽:480
python逐條解讀 瀏覽:832
基於單片機的濕度控制 瀏覽:498
ios如何使用安卓的帳號 瀏覽:882
程序員公園采訪 瀏覽:811
程序員實戰教程要多長時間 瀏覽:974
企業數據加密技巧 瀏覽:134
租雲伺服器開發 瀏覽:813
程序員告白媽媽不同意 瀏覽:335
攻城掠地怎麼查看伺服器 瀏覽:600