1. 在java中 怎麼輸入換行符到文本中
換行就是" " 或者" "
給個例子:
FileWriterfw=newFileWriter("f:\text.txt");
fw.write(" ");
fw.flush();
2. 在 java 中,怎樣替換一個 String 字元串中的第 n 個字元呢
你好提問者:
如果解決了你的問題,請採納,若有疑問請追問,謝謝!
packagecom.zyx.cn._test;
publicclassTest{
publicstaticvoidmain(String[]args){
Strings="asdasdas";
intnumber=0;
Stringstr="";
for(inti=0;i<s.length();i++){
StringnewChar=s.substring(i,i+1);
if("a".equals(newChar)||newChar=="a"){
number++;
if(number==3){
str=s.substring(0,i);
str=str+"b"+s.substring(i+1,s.length());
System.out.println(str);
}
}
}
}
}
結果:
asdasdbs
3. java中實現換行的幾種方法
java中實現換行有以下幾種方法:
1.使用java中的轉義符"\r\n":
String str="aaa";
str+="\r\n";
這樣在str後面就有換行了.
注意:\r,\n的順序是不能夠對換的,否則不能實現換行的效果.
2.BufferedWriter的newline()方法:
FileOutputStream fos=new FileOutputStream("c;\\11.txt");
BufferedWriter bw=new BufferedWriter(fos);
bw.write("你好");
bw.newline();
bw.write("java");
w.newline();
3.使用System.getProperty()方法:
String str = "aaa"+System.getProperty("line.separator");
附:針對常用的系統,可以使用如下的轉義符實現換行:
windows下的文本文件換行符:\r\n
linux/unix下的文本文件換行符:\r
Mac下的文本文件換行符:\n
4. JAVA中如何替換所有字元
使用正則表達式,直接替換所有的0-9數字
function cha(n)
{
var len=n.length;
for (var i=0;i<=len;i++)
{
var temp=/\d/;
n=n.replace(temp,"");
}
if (n!="" && n!=null){
alert(n);
return false;
}else{
alert(n);
return true;
}
}
如果是純粹為了校驗提交頁面是否使用數字,可以用這個
function isint()
{
if (isNaN(pageform.page.value))
{
alert("請輸入數字!");
return false;
}
pageform.submit();
}
5. java解析word中的文字,出現手動換行符,就是向下的箭頭,怎麼替換為\n
word中出現的向下的箭頭,其實叫軟回車符,也叫手動換行符,而我們平常在word中所見的是硬回車,一個轉彎的箭頭。軟回車的符號是「^l 」,硬回車的符號是「^p」。
可以通過查找和替換命令來消除。
操作步驟:
1、開始---->查找,如圖所示;
2、彈出和替換對話框,在查找內容中輸入「^l 」,替換內容為空,點擊全部替換就會將軟回車全部替換掉,如圖所示。
6. Java類的熱替換——概念、設計與實現
對於許多關鍵性業務或者龐大的 Java 系統來說 如果必須暫停系統服務才能進行系統升級 既會大大影響到系統的可用性 同時也增加了系統的管理和維護成本 因此 如果能夠方便地在不停止系統業務的情況下進行系統升級 則可以很好地解決上述問題 在本文中 我們將基於實例 對構建在線升級 Java 系統的基礎技術和設計原則進行了深入的講解 相信讀者能夠根據文中的技術構建出自己的在線升級系統來
Java ClassLoader 技術剖析
在本文中 我們將不對 Java ClassLoader 的細節進行過於詳細的講解 而是關注於和構建在線升級系統相關的基礎概念 關於 ClassLoader 的詳細細節許多資料可以參考 有興趣的讀者可以自行研讀
要構建在線升級系統 一個重要的技術就判如是能夠實現 Java 類的熱替換 —— 也就是在不停止正在運行的系統的情況下進行類(對象)的升級替換 而 Java 的 ClassLoader 正是實現這項技術的基礎
在 Java 中 類銷數的實例化流程分為兩個部分 類的載入和類的實例化 類的載入又分為顯式載入和隱式載入 大家使用 new 關鍵字創建類實例時 其實就隱式地包含了類的載入過程 對於類的顯式載入來說 比較常用的是 Class forName 其實 它們都是通過調用 ClassLoader 類的 loadClass 方法來完成類的實際載入工作的 直接調用 ClassLoader 的 loadClass 方法是另外一種不常用的顯式載入類的技術
圖 Java 類載入器層次結構圖
ClassLoader 在載入類時有一定的層次關系和規則 在 Java 中 有四種類型的類載入器 分別為 BootStrapClassLoader ExtClassLoader AppClassLoader 以及用戶自定義的 ClassLoader 這四種類載入器分別負責不同路徑的類的載入 並形成了一個類載入的層次結構
BootStrapClassLoader 處於類載入器層次結構的最高層 負責 sun boot class path 路徑下類的載入 默認為 jre/lib 目錄下的核心 API 或 Xbootclasspath 選項指定的 jar 包 ExtClassLoader 的載入路徑為 java ext dirs 默認為 jre/lib/ext 目錄或者 Djava ext dirs 指定目錄下的 jar 包載入 AppClassLoader 的載入路徑為 java class path 默認為環境變數 CLASSPATH 中設定的值 也可以通過 classpath 選型進行指定 用戶自定義 ClassLoader 可以根據用戶的需要定製自己的類載入過程 在運行期進行指定類的動態實時載入
這四種類載入器的層次關系圖如 圖 所示 一般來說 這四種類載入器會形成一種父子關系 高層為低層的父載入器 在進行類載入時 首先會自底向上挨個檢查是否已經載入了指定類 如果已經載入則直接返回該類的引用 如果到最高層也沒有載入過指定類 那麼會自頂向下挨個嘗試載入 直到用戶自定義類載入器 如果還不能成功 就會拋出異常 Java 類的載入過程如 圖 所示
圖 Java 類的載入過程
每個類載入器有自己的名字空間 對於同一個類載入器實例來說 名字相同的類只能存在一個 並且僅載入一次 不管該類有沒有變化 下次再需要載入時 它只是從自己的緩存中直接返回已經載入過的類引用
我們編寫的應用類默認情況下都是通過 AppClassLoader 進行載入的 當虧沖首我們使用 new 關鍵字或者 Class forName 來載入類時 所要載入的類都是由調用 new 或者 Class forName 的類的類載入器(也是 AppClassLoader)進行載入的 要想實現 Java 類的熱替換 首先必須要實現系統中同名類的不同版本實例的共存 通過上面的介紹我們知道 要想實現同一個類的不同版本的共存 我們必須要通過不同的類載入器來載入該類的不同版本 另外 為了能夠繞過 Java 類的既定載入過程 我們需要實現自己的類載入器 並在其中對類的載入過程進行完全的控制和管理
編寫自定義的 ClassLoader
為了能夠完全掌控類的載入過程 我們的定製類載入器需要直接從 ClassLoader 繼承 首先我們來介紹一下 ClassLoader 類中和熱替換有關的的一些重要方法
findLoadedClass 每個類載入器都維護有自己的一份已載入類名字空間 其中不能出現兩個同名的類 凡是通過該類載入器載入的類 無論是直接的還是間接的 都保存在自己的名字空間中 該方法就是在該名字空間中尋找指定的類是否已存在 如果存在就返回給類的引用 否則就返回 null 這里的直接是指 存在於該類載入器的載入路徑上並由該載入器完成載入 間接是指 由該類載入器把類的載入工作委託給其他類載入器完成類的實際載入
getSystemClassLoader Java 中新增的方法 該方法返回系統使用的 ClassLoader 可以在自己定製的類載入器中通過該方法把一部分工作轉交給系統類載入器去處理
defineClass 該方法是 ClassLoader 中非常重要的一個方法 它接收以位元組數組表示的類位元組碼 並把它轉換成 Class 實例 該方法轉換一個類的同時 會先要求裝載該類的父類以及實現的介面類
loadClass 載入類的入口方法 調用該方法完成類的顯式載入 通過對該方法的重新實現 我們可以完全控制和管理類的載入過程
resolveClass 鏈接一個指定的類 這是一個在某些情況下確保類可用的必要方法 詳見 Java 語言規范中 執行 一章對該方法的描述
了解了上面的這些方法 下面我們來實現一個定製的類載入器來完成這樣的載入流程 我們為該類載入器指定一些必須由該類載入器直接載入的類集合 在該類載入器進行類的載入時 如果要載入的類屬於必須由該類載入器載入的集合 那麼就由它直接來完成類的載入 否則就把類載入的工作委託給系統的類載入器完成
在給出示例代碼前 有兩點內容需要說明一下 要想實現同一個類的不同版本的共存 那麼這些不同版本必須由不同的類載入器進行載入 因此就不能把這些類的載入工作委託給系統載入器來完成 因為它們只有一份 為了做到這一點 就不能採用系統默認的類載入器委託規則 也就是說我們定製的類載入器的父載入器必須設置為 null 該定製的類載入器的實現代碼如下
class CustomCL extends ClassLoader {
private String basedir; // 需要該類載入器直接載入的類文件的基目錄
private HashSet dynaclazns; // 需要由該類載入器直接載入的類名
public CustomCL(String basedir String[] clazns) {
super(null); // 指定父類載入器為 null
this basedir = basedir;
dynaclazns = new HashSet();
loadClassByMe(clazns);
}
private void loadClassByMe(String[] clazns) {
for (int i = ; i < clazns length; i++) {
loadDirectly(clazns[i]);
dynaclazns add(clazns[i]);
}
}
private Class loadDirectly(String name) {
Class cls = null;
StringBuffer *** = new StringBuffer(basedir);
String classname = name replace( File separatorChar) + class ;
*** append(File separator + classname);
File classF = new File( *** toString());
cls = instantiateClass(name new FileInputStream(classF)
classF length());
return cls;
}
private Class instantiateClass(String name InputStream fin long len){
byte[] raw = new byte[(int) len];
fin read(raw);
fin close();
return defineClass(name raw raw length);
}
protected Class loadClass(String name boolean resolve)
throws ClassNotFoundException {
Class cls = null;
cls = findLoadedClass(name);
if(!ntains(name) && cls == null)
cls = getSystemClassLoader() loadClass(name);
if (cls == null)
throw new ClassNotFoundException(name);
if (resolve)
resolveClass(cls);
return cls;
}
}
在該類載入器的實現中 所有指定必須由它直接載入的類都在該載入器實例化時進行了載入 當通過 loadClass 進行類的載入時 如果該類沒有載入過 並且不屬於必須由該類載入器載入之列都委託給系統載入器進行載入 理解了這個實現 距離實現類的熱替換就只有一步之遙了 我們在下一小節對此進行詳細的講解
實現 Java 類的熱替換
在本小節中 我們將結合前面講述的類載入器的特性 並在上小節實現的自定義類載入器的基礎上實現 Java 類的熱替換 首先我們把上小節中實現的類載入器的類名 CustomCL 更改為 HotswapCL 以明確表達我們的意圖
現在來介紹一下我們的實驗方法 為了簡單起見 我們的包為默認包 沒有層次 並且省去了所有錯誤處理 要替換的類為 Foo 實現很簡單 僅包含一個方法 sayHello
清單 待替換的示例類
public class Foo{
public void sayHello() {
System out println( hello world! (version one) );
}
}
在當前工作目錄下建立一個新的目錄 swap 把編譯好的 Foo class 文件放在該目錄中 接下來要使用我們前面編寫的 HotswapCL 來實現該類的熱替換 具體的做法為 我們編寫一個定時器任務 每隔 秒鍾執行一次 其中 我們會創建新的類載入器實例載入 Foo 類 生成實例 並調用 sayHello 方法 接下來 我們會修改 Foo 類中 sayHello 方法的列印內容 重新編譯 並在系統運行的情況下替換掉原來的 Foo class 我們會看到系統會列印出更改後的內容 定時任務的實現如下(其它代碼省略 請讀者自行補齊)
public void run(){
try {
// 每次都創建出一個新的類載入器
HowswapCL cl = new HowswapCL( /swap new String[]{ Foo });
Class cls = cl loadClass( Foo );
Object foo = cls newInstance();
Method m = foo getClass() getMethod( sayHello new Class[]{});
m invoke(foo new Object[]{});
} catch(Exception ex) {
ex printStackTrace();
}
}
編譯 運行我們的系統 會出現如下的列印
圖 熱替換前的運行結果
好 現在我們把 Foo 類的 sayHello 方法更改為
public void sayHello() {
System out println( hello world! (version o) );
}
在系統仍在運行的情況下 編譯 並替換掉 swap 目錄下原來的 Foo class 文件 我們再看看屏幕的列印 奇妙的事情發生了 新更改的類在線即時生效了 我們已經實現了 Foo 類的熱替換 屏幕列印如下
圖 熱替換後的運行結果
敏銳的讀者可能會問 為何不用把 foo 轉型為 Foo 直接調用其 sayHello 方法呢?這樣不是更清晰明了嗎?下面我們來解釋一下原因 並給出一種更好的方法
如果我們採用轉型的方法 代碼會變成這樣 Foo foo = (Foo)cls newInstance(); 讀者如果跟隨本文進行試驗的話 會發現這句話會拋出 ClassCastException 異常 為什麼嗎?因為在 Java 中 即使是同一個類文件 如果是由不同的類載入器實例載入的 那麼它們的類型是不相同的 在上面的例子中 cls 是由 HowswapCL 載入的 而 foo 變數類型聲名和轉型里的 Foo 類卻是由 run 方法所屬的類的載入器(默認為 AppClassLoader)載入的 因此是完全不同的類型 所以會拋出轉型異常
那麼通過介面調用是不是就行了呢?我們可以定義一個 IFoo 介面 其中聲名 sayHello 方法 Foo 實現該介面 也就是這樣 IFoo foo = (IFoo)cls newInstance(); 本來該方法也會有同樣的問題的 因為外部聲名和轉型部分的 IFoo 是由 run 方法所屬的類載入器載入的 而 Foo 類定義中 implements IFoo 中的 IFoo 是由 HotswapCL 載入的 因此屬於不同的類型轉型還是會拋出異常的 但是由於我們在實例化 HotswapCL 時是這樣的
HowswapCL cl = new HowswapCL( /swap new String[]{ Foo });
其中僅僅指定 Foo 類由 HotswapCL 載入 而其實現的 IFoo 介面文件會委託給系統類載入器載入 因此轉型成功 採用介面調用的代碼如下
清單 採用介面調用的代碼
public void run(){
try {
HowswapCL cl = new HowswapCL( /swap new String[]{ Foo });
Class cls = cl loadClass( Foo );
IFoo foo = (IFoo)cls newInstance();
foo sayHello();
} catch(Exception ex) {
ex printStackTrace();
}
}
確實 簡潔明了了很多 在我們的實驗中 每當定時器調度到 run 方法時 我們都會創建一個新的 HotswapCL 實例 在產品代碼中 無需如此 僅當需要升級替換時才去創建一個新的類載入器實例
在線升級系統的設計原則
在上小節中 我們給出了一個 Java 類熱替換的實例 掌握了這項技術 就具備了實現在線升級系統的基礎 但是 對於一個真正的產品系統來說 升級本省就是一項非常復雜的工程 如果要在線升級 就會更加復雜 其中 實現類的熱替換只是最後一步操作 在線升級的要求會對系統的整體設計帶來深遠的影響 下面我們來談談在線升級系統設計方面的一些原則
在系統設計一開始 就要考慮系統的哪些部分是需要以後在線升級的 哪些部分是穩定的
雖然我們可以把系統設計成任何一部分都是可以在線升級的 但是其成本是非常高昂的 也沒有必要 因此 明確地界定出系統以後需要在線升級的部分是明智之舉 這些部分常常是系統業務邏輯規則 演算法等等
設計出規范一致的系統狀態轉換方法
替換一個類僅僅是在線升級系統所要做的工作中的一個步驟 為了使系統能夠在升級後正常運行 就必須保持升級前後系統狀態的一致性 因此 在設計時要考慮需要在線升級的部分所涉及的系統狀態有哪些 把這些狀態設計成便於獲取 設置和轉換的 並用一致的方式來進行
明確出系統的升級控制協議
這個原則是關於系統在線升級的時機和流程式控制制的 不考慮系統的當前運行狀態就貿然進行升級是一項非常危險的活動 因此在系統設計中 就要考慮並預留出系統在線升級的控制點 並定義清晰 明確的升級協議來協調 控制多個升級實體的升級次序 以確保系統在升級的任何時刻都處在一個確定的狀態下
考慮到升級失敗時的回退機制
即使我們做了非常縝密細致的設計 還是難以從根本上保證系統升級一定是成功的 對於大型分布式系統來說尤其如此 因此在系統設計時 要考慮升級失敗後的回退機制
好了 本小節我們簡單介紹了在線升級系統設計時的幾個重要的原則 下一小節我們將給出一個簡單的實例 來演示一下如何來實現一個在線升級系統
在線升級系統實例
首先 我們來簡單介紹一下這個實例的結構組成和要完成的工作 在我們的例子中 主要有三個實體 一個是升級控制實體 兩個是工作實體 都基於 ActiveObject 實現
升級控制實體以 RMI 的方式對外提供了一個管理命令介面 用以接收外部的在線升級命令 工作實體有兩個消息隊列 一個用以接收分配給它的任務(我們用定時器定時給它發送任務命令消息) 我們稱其為任務隊列 另一個用於和升級控制實體交互 協作完成升級過程 我們稱其為控制隊列 工作實體中的任務很簡單 就是使用我們前面介紹的 Foo 類簡單地列印出一個字元串 不過這次字元串作為狀態保存在工作實體中 動態設置給 Foo 類的實例的 升級的協議流程如下
當升級控制實體接收到來自 RMI 的在線升級命令時 它會向兩個工作實體的任務隊列中發送一條准備升級消息 然後等待回應 當工作實體在任務隊列中收到准備升級消息時 會立即給升級控制實體發送一條准備就緒消息 然後切換到控制隊列等待進一步的升級指令 升級控制實體收齊這兩個工作實體發來的准備就緒消息後 就給這兩個工作實體的控制隊列各發送一條開始升級消息 然後等待結果 工作實體收到開始升級消息後 進行實際的升級工作 也就是我們前面講述的熱替換類 然後 給升級控制實體發送升級完畢消息 升級控制實體收到來自兩個工作實體的升級完畢消息後 會給這兩個工作實體的控制隊列各發送一條繼續工作消息 工作實體收到繼續工作消息後 切換到任務隊列繼續工作 升級過程結束
主要的代碼片段如下(略去命令消息的定義和執行細節)
清單 主要的代碼片段
// 升級控制實體關鍵代碼
class UpgradeController extends ActiveObject{
int nready = ;
int nfinished = ;
Worker[] workers;
// 收到外部升級命令消息時 會觸發該方法被調用
public void askForUpgrade() {
for(int i= ; i<workers length; i++)
workers[i] getTaskQueue() enqueue(new PrepareUpgradeCmd(workers[i]));
}
// 收到工作實體回應的准備就緒命令消息時 會觸發該方法被調用
public void readyForUpgrade(String worker_name) {
nready++;
if(nready == workers length){
for(int i= ; i<workers length; i++)
workers[i] getControlQueue() enqueue(new
StartUpgradeCmd(workers[i]));
}
}
// 收到工作實體回應的升級完畢命令消息時 會觸發該方法被調用
public void finishUpgrade(String worker_name) {
nfinished++;
if(nfinished == workers length){
for(int i= ; i<workers length; i++)
workers[i] getControlQueue() enqueue(new
ContineWorkCmd(workers[i]));
}
}
}
// 工作實體關鍵代碼
class Worker extends ActiveObject{
UpgradeController ugc;
HotswapCL hscl;
IFoo foo;
String state = hello world! ;
// 收到升級控制實體的准備升級命令消息時 會觸發該方法被調用
public void prepareUpgrade() {
switchToControlQueue();
ugc getMsgQueue() enqueue(new ReadyForUpdateCMD(ugc this));
}
// 收到升級控制實體的開始升級命令消息時 會觸發該方法被調用
public void startUpgrade(String worker_name) {
doUpgrade();
ugc getMsgQueue() enqueue(new FinishUpgradeCMD(ugc this));
}
// 收到升級控制實體的繼續工作命令消息時 會觸發該方法被調用
public void continueWork(String worker_name) {
switchToTaskQueue();
}
// 收到定時命令消息時 會觸發該方法被調用
public void doWork() {
foo sayHello();
}
// 實際升級動作
private void doUpgrade() {
hscl = new HowswapCL( /swap new String[]{ Foo });
Class cls = hscl loadClass( Foo );
foo = (IFoo)cls newInstance();
foo SetState(state);
}
}
//IFoo 介面定義
interface IFoo {
void SetState(String);
void sayHello();
}
在Foo 類第一個版本的實現中 只是把設置進來的字元串直接列印出來 在第二個版本中 會先把設置進來的字元串變為大寫 然後列印出來 例子很簡單 旨在表達規則或者演算法方面的升級變化 另外 我們並沒有提及諸如 消息超時 升級失敗等方面的異常情況 這在實際產品開發中是必須要考慮的
lishixin/Article/program/Java/hx/201311/26326
7. java 替換文件內容
代碼如下:
/***
* 方法:
* @Title: replaceContentToFile
* @Description: TODO
* @param @param path 文件
* @param @param str 開始刪除的字元
* @param @param con 追加的文本
* @return void 返回類型
* @throws
*/
public static void replaceContentToFile(String path, String str ,String con){
try {
FileReader read = new FileReader(path);
BufferedReader br = new BufferedReader(read);
StringBuilder content = new StringBuilder();
while(br.ready() != false){
content.append(br.readLine());
content.append("\r\n");
}
System.out.println(content.toString());
int dex = content.indexOf(str);
if( dex != -1){
System.out.println(content.substring(dex, content.length()));
content.delete(dex, content.length());
}
content.append(con);
br.close();
read.close();
FileOutputStream fs = new FileOutputStream(path);
fs.write(content.toString().getBytes());
fs.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}