マルチバイト対応のsubstr

このQ&Aのポイント
  • マルチバイト対応のsubstrを使用してプログラミングをしていましたが、一部不具合が発生しています。
  • substrのマルチバイト対応はニーズが高いと考えられ、既に実装例が存在する可能性があります。
  • JScript・htaでアプリを作成しており、IE4以降で動作するJavaScriptのマルチバイト対応substrの動作するコードを教えてください。
回答を見る
  • ベストアンサー

マルチバイト対応のsubstr

substrを使ってプログラミングをしていました。 うまく動いているはずなのに一部不具合がありました。 それが、日本語が含まれた部分の切り出しでした…。 これくらい用意してくれてもいいのにと思いつつ途方にくれています。 でもsubstrのマルチバイト対応というのはニーズが高いと思うので 今までに書いたことがある人というのはいるはずではないかと思いました。 まる投げで申し訳ないのですが、マルチバイトに対応したsubstrこれを教えてください。 (できれば動くコードそのもの) 環境はJScript・htaでアプリを作っています。 IE4以降で動くJavaScriptならOKです。 よろしくお願いします。

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

  • ベストアンサー
  • mibusys
  • ベストアンサー率60% (18/30)
回答No.3

No.1の補足から推測する限り、SJISと同じように全角を2バイトとカウントしてほしいということですよね。 Stringオブジェクトを拡張する形で作ってみました。多少苦労しましたが勉強になりました。 2バイト目が指定されてしまう時にはエラーにはせずに該当文字位置からカウントを開始する、 2バイト文字の1バイト目で終了する場合にはその文字を壊さずに返すという仕様にしてみました。 つくりがまだしょぼいのですがとりあえず動きます。どうでしょう? String.prototype.lengthB = function() { var len = 0; for (var i = 0; i < this.length; i++) { if (this.charAt(i).isMultibyte()) { len += 2; } else { len += 1; } } return len; } String.prototype.substrB = function() { var fromByte = arguments[0]; var retByte = arguments[1]; // 開始位置の検索 var len = 0; var i; for (i = 0; fromByte > len; i++) { if (this.charAt(i).isMultibyte()) { len += 2; } else { len += 1; } } var from = i; len = 0; var retLen = 0; while(retByte > len) { if (this.charAt(i).isMultibyte()) { len = len + 2; } else { len = len + 1; } retLen++; i++; } return this.substr(from, retLen); } String.prototype.isMultibyte = function() { var c = this.charCodeAt(0); // 半角の範囲 // Unicode : 0x0 ~ 0x80, 0xf8f0, 0xff61 ~ 0xff9f, 0xf8f1 ~ 0xf8f3 if ((c >= 0x0 && c <= 0x80) || (c == 0xf8f0) || (c >= 0xff61 && c <= 0xff9f) || (c >= 0xf8f1 && c <= 0xf8f3)) { return false; } else { return true; } }

pringlez
質問者

お礼

いろいろ期待通りでした。完璧です。 ・日本語を2バイトとしてカウントする ・エラーが出ない柔軟なつくりになっている ・substrの仕様を踏襲している というかメソッドをStringに直接追加するあたりはむしろ期待以上です。 ありがとうございました。

その他の回答 (2)

  • think49
  • ベストアンサー率59% (285/482)
回答No.2

> バイト単位でカウントしてほしいという意味です。 以下、IE8,Firefox3で動作確認済みです。 # バイト範囲を誤るとエラーになる問題は妥協しました。 # 修正するなら、charAtを使用してデコードできない場合はエラーを返すのが妥当かと思います。 ---- <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'> <html lang='ja' xml:lang='ja' xmlns='http://www.w3.org/1999/xhtml'> <head> <meta http-equiv='content-type' content='text/html; charset=utf-8' /> <meta http-equiv='content-style-type' content='text/css' /> <meta http-equiv='content-script-type' content='text/javascript' /> <meta name='author' content='think' /> <title>バイト単位で指定するsubstr</title> </head> <body> <script type='text/javascript'> (function(){ function substrByte(str, start, end){ str = encodeURIComponent(str); var i = 0, target = ''; str.match(/^/); // RegExp.rightContextの初期化 while(RegExp.rightContext){ RegExp.rightContext.match(/^(%[\da-z]{2}|.)/i); if(i >= start && i <= end){ target += RegExp.$1; } if(i == end){ break; } i++; } return decodeURIComponent(target); } var str = 'バイト単位で指定するsubstr'; var target = substrByte(str, 0, 2); // "バ" を抽出 (UTF-8は3バイト) document.body.appendChild(document.createTextNode(target)); })(); </script> </body> </html> ----

参考URL:
http://www.openspc2.org/reibun/javascript/string/026/
pringlez
質問者

お礼

せっかく作っていただいたのですが以下の理由から使えませんでした。すみません。 ・日本語を3バイトとカウントしてしまう ・エラーがですぎ ・引数の意味がsubstrの仕様と異なる(slice,substring的な仕様になっている) でもありがとうございました。

  • think49
  • ベストアンサー率59% (285/482)
回答No.1

> それが、日本語が含まれた部分の切り出しでした…。 IE8で検証しましたが、substrでマルチバイト文字を切り出しできています。 substrとは別に原因があるのでは…。 <script type="text/javascript"> var str = 'マルチバイト対応のsubstr'; alert(str.substr(0,6)); // "マルチバイト" がalertされる </script>

pringlez
質問者

お礼

ありがとうございました。

pringlez
質問者

補足

すみません。説明不足でした。 バイト単位でカウントしてほしいという意味です。 ご提示の例では「マルチ」という結果を返してほしいということです。 もし回答可能でしたらよろしくお願いします。

関連するQ&A

  • plpgsqlでのbyte数指定での文字切り出し

    postgresql(plpgsql)にて、byte数指定での文字列切り出しを行いたいのですが、よい手法などありませんか? substr(substring)だと、文字数の指定となり、対象がマルチバイト、シングルバイト文字混在だと意図した値が取得できません。 ※Oracleのsubstrbに相当するものです。 ※select substr(カラム, 1, 20) from ...的な取得がしたいです。 よろしくお願いします。

  • マルチバイトでsubstr_replace

    $comment = "全角hannkaku全角"; $comment = substr_replace($comment, "全角", 2,8); //上記を簡潔に実現するにはどうしたらよいでしょうか?

    • 締切済み
    • PHP
  • リッチなテーブルについて

    お疲れ様です。 連休中に申し訳ありません。 htmlとjavascriptで、以下のようなリッチなテーブルを作成したいです。 ・excelのように列を固定してスクロールをしたい ・各列幅をドラッグ&ドロップで変更ができるようにしたい ・どのブラウザ(IE、FieFox、Safari)でも対応 いろんなサイトのを試みたところ、一長一短でうまくいきません。 どのように作成をしたらいいのか途方にくれています。 お願いします。 以上です。

  • よろしくお願いします。

    よろしくお願いします。 どうしてもネットスケープ7.1での対応をしなければならいのですが、flashが表示されず、 困っています。 flashに代替の画像を入れるようにしましたが、javaの関係なのか、代替の画像も表示できません。 ネットスケープ7.1でjavaを有効にするにはどうしたらよいのでしょうか? (javaを有効にするにチェックは入れています) またはブラウザ判別をしたほうがいいのかと思いますが、どなたかネットスケープだけ表示されるものを教えていただけないでしょうか? IEのバージョンを判別するものは見つけたのですが、以下のものをネットスケープだけ表示 させるにはどう書けばよいのかわかりません。 <script type="text/javascript"> (function(){ //@cc_on var flag = /*@if(@_jscript_version < 5.8)!@end@*/ false; if( flag )//IEのver7以下だけtrue,それ以外はfalse window.location.href = "http://210.171.213.36/index.html"; })(); </script> おわかりになる方、教えていただけますでしょうか? よろしくお願いいたします。

  • substrについて

    入力ファイルから28文字分のファイル名を取り出し、リモートからローカルにダウンロードしたいのですが、substrがうまく働きません。 どのようにすればよいのでしょうか? 以下のとおり記述しています。 open (INPUT,"<$path/$filename") || die "could not open file : $!\n"; print "$path/$filenameファイルをオープンしました。"; print "\n"; while(<INPUT>) { $FTPremotefilename = substr($_,0,28); print "FTPremotefile名は$_です。"; print "\n"; $FTP -> get($FTPremotefile, $FTPlocalfile) || die "Get失敗 $!\n";# ゲット(ファイルのダウンロード) } close (INPUT) || die "could not close file : $!\n"; $_は内容が表示されるのですが、substrで指定した、$FTPremotefileになにも抽出されませんでした。

    • ベストアンサー
    • Perl
  • フレッツスクエアが利用できない。

    Bフレッツに加入しており、ルータはCG-WLBARAGLを使用しています。 ルータはマルチセッションに対応しており、設定もできているはずなんですが、IE上でhttp://www.flets/と入力してもフレッツスクエアを利用できません。 ルータのステータスでは、フレッツスクエアの接続が通信中となっていて接続できているはずなんですが…。 どうしたらフレッツスクエアを利用できるようになるんでしょうか?

  • ブラウザによって異なる外部javascriptを適応させるには?

    現在作成しているページがあるのですが、 外部javascriptを読み込む仕様となっております。 ですが、javascriptがブラウザによって、 動作が異なることで頭を悩ませています。 ※firefox, ie6, ie7, operaの4つそれぞれ個別に指示したいと思っています。 従いまして、そこで考えたのが、推測なので、できるかどうかは分からないのですが、、、以下の2つの方法になります。 1.ブラウザ毎に一つのjsファイルを用意する。 →この場合、4つのブラウザに対応させる必要があるので、4つのjsファイルが必要になります。 →具体的な方法としては、一つの判別javascriptファイルを用意しておいて、その中でさらに4分岐させて、それぞれ別のjsファイルを読み込む? 以下がokweb内では、それらしいなと思いましたが、これはそのまま使うことができるのでしょうか。 http://okwave.jp/qa3365142.html 2.一つのjsファイル内で、ブラウザ毎に別々の命令文を書いておく。 →技術的に無理? おそらく、1番の方法が、私がネットで調べた限りは、有力そうなのですが、検索しても、非常に古い記事ばかりがヒットしました。 現在のトレンドともいうべき、最も信頼性の高いブラウザ判別の方法というのは何になるのでしょうか。 この場合、phpなど、サーバーサイドのプログラムは含まず、あくまでも、javascriptでの判別方法を具体的に助言していただければと思います。 宜しくお願いします。

  • ブラウザによる表示の違い

    今サイトを作成しています。 HTML、CSSをはじめて1年の初心者です。 ブラウザは普段基本的にFirefoxを使用しています。 サイトの表示確認をFirefoxとIE7で行っているのですが2つのブラウザで微妙に表示がずれてしまいます。 色々調べてJavaScriptでブラウザを判別させてそれぞれに対応したページを用意するようなことが書かれていたんですがいまいちやり方がよくわかりません、、 やり方知ってる方助けてください。 もしくは他の対処法があるんでしたら教えていただけると助かります。 よろしくお願いします。

    • ベストアンサー
    • HTML
  • substrの使い方

    文字列の一部だけを表示するため「substr」を利用しようとしていますが、うまくできません。 問題となっているのは2点です。 1.半角英数のみと日本語のみで長さが全然違う。 2.半角英数+日本語で日本語で切れるとき、最後の文字が文字化けする。 これを解決したいのですが、どうしたらよいでしょうか? 現状は以下のようになっています。 #文字数を指定 $mc = 38; #題名を短くする if (length($title) > $mc) {   $title = substr($title,0,$mc);   $title .= "..."; }

    • 締切済み
    • CGI
  • JavaScriptによるDBアクセス時のDATE型の扱い

    JavaScriptによるDBアクセス時のDATE型の扱い ADODBとODBCを用い、Oracle10gに対してアクセスしています。 このとき、OracleのDATE型のカラムをJavaScriptで 受ける際の型で困っています。 HTAとして実行しており、IEのバージョンは7です。 JavaScriptで受けた値をtypeofで確認すると「date」と表示されます。 値を何も指定せずに文字列化すると 「Mon Jul 18 00:00:00 UTC+0900 2010」等の文字列になります。 ですので、JavaScriptのDate型であるように思えました。 受け取りたい形は「yyyy/MM/dd hh:mm:ss」という形なので、 「getYear」「getMonth」等の関数を使用して年部分・月部分を 個別に取得しようとしたところ「オブジェクトを指定してください」 というスクリプトエラーが発生しました。 確認の為、「alert(typeof(new Date()));」を実行してみたところ 「object」と表示されました…。当然ですがこちらの型であれば 「getYear」「getMonth」等の関数を使用することが出来ます。 つまり、JavaScriptで普通にnew Date()として使用する型と DBにアクセスして取得する値の型は、異なっているらしい というところまでは分かりました。 以下を教えてください。 ・DBアクセスして取得されるこの「date型」は何者ですか? ・この「date」をJavaScriptの「Date型」に変換する方法があればそれを ・この「date」から、年・月等の値を取得する方法 ・「date」オブジェクトの持つ関数をプログラミング的に調べる方法 ・「date」オブジェクトの持つ関数の一覧等のリファレンス的Webページ よろしくお願いします。

専門家に質問してみよう