• ベストアンサー

メタキャラクタのエスケープについて

がんばって調べているんですが、わからないので質問します。 HTMLでのメタキャラクタ(「<」「>」「&」「"」など)を エスケープしたいんですが、うまくいきません。 試した内容は、こんな感じです。 Stringクラスのreplace(char oldChar, char newChar) を使えば、上手くいくかなと思ったのですが、文字列の 長さが変わってしまう為、使えませんでした。 1文字と1文字の変換だとうまく行くのですが、今回の 場合、1文字を4文字に変換したい為、使えません^^; < → &lt; 次に考えたのが、文字列のバッファの長さを増やせる Stringbufferクラスの replace(int start, int end, String str) だと、位置を指定しなければならなくて、どうやったら 良いのかわかりません。 みなさん、どのようにしているのでしょうか? 考え方、サンプルなどありましたら、アドバイスお願いします。

  • Java
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

> Stringbufferクラスの > replace(int start, int end, String str) > だと、位置を指定しなければならなくて、どうやったら > 良いのかわかりません。 位置は探してゆけば良いですね。例えば、こんな感じ。 StringBuffer buf = new StringBuffer(対象の文字列); for (int i = 0 ; i < buf.length() ; ++i) {  if ( buf.charAt(i) == '<' ) {   buf.replace(i, i+1, "&lt;");   i += 3;  } } もっとスマートな解が在りそうな気がするので、自信無しとして置きます (^^; 標準の範囲を超えてしまいますが、参考URLのようなライブラリを使えればメソッド一発ですね。

参考URL:
http://www.ingrid.org/jajakarta/regexp/jakarta-regexp-1.2/doc-jp/api/org/apache/regexp/RE.html
HELPMAN
質問者

お礼

補足部分で、足りない部分と、間違いがあったので、 お礼に書かせてもらいます。 あわてんぼうで、すいません^^; String str = "<script>test</script>犬&猫<a href=\"http://www.aaa.com\">AAAA</a>"; StringBuffer sb = new StringBuffer(str); try{  for(int i = 0 ; i < sb.length() ; ++i){   if(sb.charAt(i)=='<'){    sb.replace(i, i+1,"&lt;");    i+=3;   }   if(sb.charAt(i)=='>'){    sb.replace(i, i+1,"&gt;");    i+=3;   }   if(sb.charAt(i)=='&'){    sb.replace(i, i+1,"&amp;");    i+=4;   }   if(sb.charAt(i)=='\''){    sb.replace(i, i+1,"&apos;");    i+=5;   }   if(sb.charAt(i)=='\"'){    sb.replace(i, i+1,"&quot;");    i+=5;   }  } }catch(IndexOutOfBoundsException ex){ }

HELPMAN
質問者

補足

素早いご回答ありがとうございます。 考え方がすごいわかりやすかったです。 そして、さらに質問になりますが、「i+=3」の部分 なんですが、「&lt;」って4文字なんで、「i+=4」 にならないのでしょうか? 微妙に混乱しています^^; また、色々なメタキャラクタをエスケープするように 作ってみました。現在、「クロスサイトスクリプティング」に ついて対策を考えているのですが、ひとつわからない事が あります。 「<」「>」「&」「"」の四つの文字については、 エスケープに成功しました。しかし、「'」(シングル クォーテーション)だけは、エスケープできません。 画面に「&apos;」と出てしまいます。(IE5.5で確認) シングルクォーテーションのエスケープの仕方が間違って いるんでしょうか? それとも、シングルクォーテーションは、普通エスケープ しないのでしょうか? クロスサイトスクリプティングの場合は、シングルクォーテーション は、エスケープしなくても良いのでしょうか? かなりたくさん、質問となってしまいますので、ご存知 の部分だけでもわかりましたら、よろしくお願いします。 あと、作成したソースを載せますので、書き方などの 注意もありましたら、よろしくお願いします。 try{ for(int i = 0 ; i < sb.length() ; ++i){ if(sb.charAt(i)=='<'){ sb.replace(i, i+1,"&lt;"); i+=3; } if(sb.charAt(i)=='>'){ sb.replace(i, i+1,"&gt;"); i+=3; } if(sb.charAt(i)=='&'){ sb.replace(i, i+1,"&amp;"); i+=4; } if(sb.charAt(i)=='\''){ sb.replace(i, i+1,"&apos;"); i+=5; } if(sb.charAt(i)=='<'){ sb.replace(i, i+1,"&quot;"); i+=5; } } }catch(IndexOutOfBoundsException ioobe){ }

その他の回答 (2)

noname#16216
noname#16216
回答No.3

個人的にHTMLタグを変換する機会が多いので、以下のような関数を 持ったクラスを作って利用してます。 単純にif~elseになるべきところを、switchを使っているだけですが。。。 static public String replaceTag(String argOriginalStr) {  StringBuffer returnStr = new StringBuffer();  for (int i = 0; i < argOriginalStr.length(); i++) {   char ch = argOriginalStr.charAt(i);    switch(ch) {     case '<':      returnStr.append("&lt;");      break;     case '>':      returnStr.append("&gt;");      break;     default:      returnStr.append(ch);      break;    }   }   return new String(returnStr);  }

HELPMAN
質問者

お礼

ご回答ありがとうございます。 switchで条件分岐するやり方もありましたね! ほんと、勉強になります。 if文は、結構使用しますが、switch文は、if文に 比べると使用頻度が少なく思います。 ちょっと忘れ気味でした。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.2

> そして、さらに質問になりますが、「i+=3」の部分 > なんですが、「&lt;」って4文字なんで、「i+=4」 > にならないのでしょうか? for() で +1 されるので、+=3 としています。考え方は4文字だから4増やすで良いです。 > しかし、「'」(シングル > クォーテーション)だけは、エスケープできません。 「お礼」にあったソースで良いと思いますけどね。シングルクォートもきちんと変換できますよね。 ただ、StringBuffer#replace() で置換した後の i を増やすところでは、";" を指しているので、 if の連続ではなく、if ~ else if と続けた方が良いかも。これでも大丈夫ですけど。

HELPMAN
質問者

お礼

またまた、回答ありがとうございます。 >for() で +1 されるので、+=3 としています。 あっ!なるほどです。 合計4増えるんですね。 一人で考えてたら、+=4にして、失敗する所でした。 if~elseの方がいいかもしれませんね。 if~elseに変えて、使ってみたいと思います。 大変、勉強になりました。 最後まで、付き合って頂いて、感謝しております。 ありがとうございました。 「a-kuma」さんの名前は、「あ~熊さん」なのか、 「ええ熊さん」なのか、すごい気になりますが、 「ええ熊さん」だと思っておきます。 「優しい熊さん」という意味で。 すぐに締め切っても良いのですが、他の方で違った アドバイスがあるよって人がいるかもしれませんので、 明日締め切らせていただきます。 ご了承ください^^

関連するQ&A

  • javaというか文字列について少し質問です><

    javaというか文字列について少し質問です>< javaというか文字列について少し質問です>< お願いします。 シーザー暗号で文字列をずらすためのクラスのメソッドをつくったのですが・・・ String decrypt(String str,int key) { StringBuffer sb = new StringBuffer(); // もしくはStringBuilder for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c-key); sb.append( c ); } こんな感じなのですがアルファベットの小文字26文字のみとしたいので暗号化や復号化の際に越えてしまう場合はアルファベット内でループさせたいのですがいまいちやり方が浮かびません><越えてしまう場合はzからひいたものを表現させれば良いかと思いやってみたのですが全然違う文字が出てきてしまいました。何かいい方法を教えてください。お願いします><

    • ベストアンサー
    • Java
  • avaというか文字列について少し質問です><

    avaというか文字列について少し質問です>< お願いします。 シーザー暗号で文字列をずらすためのクラスのメソッドをつくったのですが・・・ String decrypt(String str,int key) { StringBuffer sb = new StringBuffer(); // もしくはStringBuilder for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c-key); sb.append( c ); } こんな感じなのですがアルファベットの小文字26文字のみとしたいので暗号化や復号化の際に越えてしまう場合はアルファベット内でループさせたいのですがいまいちやり方が浮かびません><越えてしまう場合はzからひいたものを表現させれば良いかと思いやってみたのですが全然違う文字が出てきてしまいました。何かいい方法を教えてください。お願いします><

    • ベストアンサー
    • Java
  • javaについて質問です。

    javaについて質問です。 シーザー暗号の暗号化と復号化のプログラムをつくりたいのですが... import java.io.*; class Prob6_2 { public static void main(String [] args)throws IOException { int key; //キー番号 String orgStr; //ターゲット文字列 String encStr; //暗号化文字列 String decStr; // 復号化文字列 String temp; BufferedReader br= new BufferedReader(new InputStreamReader(System.in)); System.out.print("ターゲット文字列:"); orgStr=br.readLine(); System.out.print("キー番号:"); temp=br.readLine(); key=Integer.parseInt(temp); Cipher cip=new Cipher (); encStr=cip.encrypt(orgStr,key); decStr=cip.decrypt(encStr,key); System.out.println("[Original Code]"+orgStr); System.out.println("[Encrypted Code]"+encStr); System.out.println("[Decrypted Code]"+decStr); } } class Cipher { String encrypt(String str,int key) { for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c+key); /*この後どのように一つずつの文字をつなげて文字列にしたら良いか分かりません。StringBuffer クラスのインスタンス をつかうといいというヒントは問題集に書いてあるのですが....教えて下さい*/ } } String decrypt(String str,int key) { for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c-key); /*この後どのように一つずつの文字をつなげて文字列にしたら良いか分かりません。StringBuffer クラスのインスタンス をつかうといいというヒントは問題集に書いてあるのですが....教えて下さい*/ } } } class Cipherのところにコメントでも書いてあるのですが、一つずつの文字をつなげて文字列にしたら良いか分かりません。どのように実現したら良いのでしょうか?><教えてください>< 違っているところがあればそこも教えて頂けるとたすかります。 お願いします>< できたらStringBufferをつかったやり方を教えてください><」

    • ベストアンサー
    • Java
  • char型からのバイト数取得

    文字列から1文字ずつバイト数を取得(判定)したいのですが、 char型の文字のバイト数を取得するスマートな方法はありますか? 今考えているのは以下のようなコードです。 String str ="あA" for(int i=0; i < str.length(); i++) { char ch = str.charAt(i); StringBuffer SB = new StringBuffer(); SB.append(c); if(SB.toString().getBytes.length == 1) { //1バイトの処理 } else { //2バイトの処理 } }

    • ベストアンサー
    • Java
  • C/C++関数間でのStringクラスの扱い

    以下のようなコードを実行してみましたが思い通りに動いてくれません. "sample"という文字列がstrへとコピーされると思ったのですが. stringクラスのc_str()メソッドはconst char*だと言っているので無理矢理キャストしたのが原因でしょうか.stringクラスは記憶領域を自動で変更してくれるのではないのですか.それともこの挙動は仕様ですか. -------- 以下コード -------- #include <iostream> #include <string> using namespace std; int func(char *); int main(void) {     string str("");     func((char *)str.c_str());     cout << "String: " << str << endl;     return EXIT_SUCCESS; } int func(char *buf) {     buf = "sample";     return 0; } -------- 以上コード --------

  • 分からないです(;_;)

    分からないです(;_;) 2 ユーザ関数char *my_strstr(const char *str1, const char *str2)とchar *strrep(char *src, const char *sch, const char *rep)を作成する。以下にユーザ関数の詳細を示す。 ・char *my_strstr(const char *str1, const char *str2) 文字列str1の中に文字列str2が含まれているか検索して、もし含まれているならばその位置をポインタで返し、含まれていないならばNULLを返す。ただし、以下の条件をつける。 ・文字列str2が文字列str1に複数含まれている場合は、str1の先頭から見て最初に現れるstr2を返す ・標準ライブラリ関数strcmp, strstrは使わない ・char *strrep(char *s, const char *sch, const char *rep) ユーザ関数my_strstrを用いて、文字列sの中に文字列schが含まれているか検索して、もし含まれているならばその部分を文字列repで置換し、置換した文字列の次の文字の位置を返す。含まれていないならばNULLを返す。ただし、以下の条件をつける。 ・文字列schが文字列sに複数含まれている場合は、sの先頭から見て最初に現れるschを置換する。 そして、キーボードから「文字列」「検索する文字列」「置換する文字列」を入力し、ユーザ関数strrepを用いて、「文字列」の中に含まれているすべての「検索する文字列」を「置換する文字列」で置換した結果と、「検索する文字列」が含まれていた個数を表示する。 <実行結果> Input a character string :anpanman Input a character string which you want to search :an Input a character string which you want to replace :enki The character string after replace is "enkipenkimenki" count :3 Input a character string :Yamanote-Line Input a character string which you want to search :Yamanote Input a character string which you want to replace :Chuo The character string after replace is "Chuo-Line" count :1 Input a character string :abc123/.@ Input a character string which you want to search :def Input a character string which you want to replace :xyz The character string after replace is "abc123/.@" count :0

  • javaについて質問です。お願いします><

    javaについて質問です。お願いします>< シーザー暗号を実現するプログラムをじゃいたのですが、import java.io.*; class Prob6_3 { public static void main(String [] args)throws IOException { int key; //キー番号 String orgStr; //ターゲット文字列 String encStr; //暗号化文字列 String decStr; // 復号化文字列 String temp; BufferedReader br= new BufferedReader(new InputStreamReader(System.in)); System.out.print("ターゲット文字列:"); orgStr=br.readLine(); System.out.print("キー番号:"); temp=br.readLine(); key=Integer.parseInt(temp); Cipher cip=new Cipher (); encStr=cip.encrypt(orgStr,key); decStr=cip.decrypt(encStr,key); System.out.println("[Original Code]"+orgStr); System.out.println("[Encrypted Code]"+encStr); System.out.println("[Decrypted Code]"+decStr); } } class Cipher { String encrypt(String str,int key) { String ret="";             //ココです1 for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c+key); ret+=c; } return ret; } String decrypt(String str,int key) { String ret="";              //ここです2 for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c-key); ret+=c; } return ret; } }   とこんな感じになり実行もできるのですが、class CipherのString encrypt(String str,int key)やString decrypt(String str,int key)のところで一つずつ文字をつなげて文字列にするにはStringBufferクラスのインスタンスを利用すると簡単だとききました。だけど記述方法がよくわからなく使用した場合のreturn文の書き方もイマイチわかりません><なのでできるだけ詳しく教えて頂けないでしょうか??お願いします。//ココですと書いてあるところです。お願いします><

    • ベストアンサー
    • Java
  • 三つの文字を順に並べるプログラム

    三つの文字を入力して、順番に並べて表示させるプログラムが作りたいのですが、どうしたらいいのかわかりません。 二つまではできました。以下に記します import java.io.*; class Sample { public static void main(String args[]) throws IOException { System.out.println("文字列1を入力してください。"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str1=br.readLine(); System.out.println("文字列2を入力してください。"); String str2=br.readLine(); int s = 1,t = 0; if(str1.length()>str2.length()){ int len=str1.length(); StringBuffer sb=new StringBuffer(str1); while(s<len+1){ sb.insert(s,str2.charAt(t)); s=s+2; t++; } System.out.println("文字列は"+sb+"となる。"); }else{ int len=str2.length(); StringBuffer sb=new StringBuffer(str2); while(s<len+1){ sb.insert(s-1,str1.charAt(t)); s=s+2; t++; } System.out.println("文字列は"+sb+"となる。"); } } } str1に123 str2に45といった風に入力すると14253といった風になります。 これにstr3を加え、str3が6789ならば、146257389 となる風にしたいです。

    • ベストアンサー
    • Java
  • htmlentitiesとはエスケープ処理?

    htmlentitiesとはエスケープ処理をするための関数なのでしょうか? string htmlentities ( string string, int [quote_style] , string [charset] ) この関数はhtmlspecialchars()と同じですが、 HTML エンティティと等価な意味を有する文字をHTMLエンティティに変換 します。

    • ベストアンサー
    • PHP
  • C#の文字列変換

    stringオブジェクトで下記のような文字列変換をしたいのですがうまくいきません。どのようにすればできますでしょうか?ご存知の方よろしくお願いします。 str.Replace( ")", "+9"); MessageBox(str.ToSring());

専門家に質問してみよう