質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unicode

Unicodeはエンコーディングの標準規格です。1つの文字コード体系で多国語の表現を可能にすることを目指して作られています。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

Q&A

解決済

3回答

6099閲覧

UWPアプリでの文字コードの取り扱い

退会済みユーザー

退会済みユーザー

総合スコア0

UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unicode

Unicodeはエンコーディングの標準規格です。1つの文字コード体系で多国語の表現を可能にすることを目指して作られています。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

0グッド

0クリップ

投稿2017/10/07 19:05

現在C#でWebAPIを叩くUWPアプリ開発をしております.
叩いているAPIはTwitterのもので,レスポンスのボディはUTF-8のjson形式となっております.
現在,コンソールアプリでは期待通りの結果が得られており,以下のコードにてアンエスケープまで完了した生のjsonデータが得られています.

C#

1 var client = new HttpClient(); 2 client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); 3 client.DefaultRequestHeaders.Add("Authorization", authHeader); 4 5 var response = await client.GetAsync(reqUrl); 6 var res = await response.Content.ReadAsStringAsync(); 7 8 if(response.IsSuccessStatusCode) { 9 Console.OutputEncoding = Encoding.UTF8; 10 Console.WriteLine(Regex.Unescape(res)); 11 } 12 else { 13 Console.WriteLine("むねん"); 14 }

しかし,これをUWPアプリにて実装しようとすると,Regex.Unescape(res)のところで例外が発生してしまい,
System.ArgumentException: 'parsing '�'
と表示されてしまいます.

UWPアプリとコンソールアプリとではstring型の取り扱いが異なる物なのでしょうか?
型にマウスオーバーすると,UWPアプリではUnicode文字,コンソールアプリではUTF-16文字と表示されています.

どなたか解決方法を含めてご教授頂ければ幸いです.
よろしくお願いいたします.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

自己解決いたしました.
dodox86様のご指摘頂いたHTTP1.1とHTTP2.0に由来するものかどうか判断まではできませんが,UWPアプリでリクエストを送信した際にはGZipというもので通信内容が圧縮されていたようです.

HttpClientのインスタンスを生成する際に,

C#

1 var handler = new HttpClientHandler(); 2 handler.AutomaticDecompression = DecompressionMethods.GZip; 3 var client = new HttpClient(handler);

とすると,デコードされた状態でStringを得られました.
ご回答頂きましたお二人ともありがとうございました.

投稿2017/10/08 16:15

編集2017/10/08 16:19
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

先のkikukiku様の回答内容と併せて検証していただきたいのですが、本来であればHttpContent.ReadAsStringAsync はHTTPレスポンス中のcharsetの指定状況を見て、適切な文字コードで変換してstringで返してくれるもの、との認識です。その線でいくとUWPアプリではなく、コンソールアプリの方では問題ないことと矛盾します。

2つほど原因は考えられて、基本的には.NET Framework中のクラスメソッドの実装状況に依存している気がします。UWPアプリは .NET Core なので、コンソールアプリでの.NET Framework 4.x 等とは実体が違うものを使用しているはずです。(クラス階層やメソッドは見た目同じだけど、実際にロードして使っているものが違う)

それで考えますと、
0. HttpContent.ReadAsStringAsyncの動作が違う
UWPアプリの.NET Core用は実装が最小限で、HTTPレスポンス中のcharsetを意識してstringへ変換してくれない。あるいは不完全。この場合、回答者様の案で改善する可能性が高いです。

  1. Regex.Unescape の動作が違う

UWPアプリの.NET Core用のRegex.Unescapeの実装が不完全で、resで渡された文字列を正しくアンエスケープできない。この場合、1. の案では対応できない可能性があります。

あと、ちょっと考えづらいですが、上記の1.でも2.でもなく、実はawait を指定した場合の動作が微妙に異なっていて、Regex.Unescape(res) の実行時点でresのstringが未完成だ、なんてオチがあったりするかもです。Regex.Unescape(res)の実行直前に

C#

1Debug.WriteLine("res:" + res); 2string uns = Regex.Unescape(res)

などとデバッグ出力して、受信したデータが確実に入っているかも注意して確認してみてください。

投稿2017/10/08 06:43

編集2017/10/08 06:45
dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/10/08 10:39

kikukiku様の回答へのコメントでも書かせて頂きましたが,1.Streamで取得してUTF8で読み出した場合でも,同じ文字化けの状態となっています. また,Regex.Unescapeの動作についてですが,現在そちらは未検証ですが,このメソッドへ引数として与える文字列が,エスケープ文字以外がほぼすべて文字化けしている状態(中身は存在している)となっており,その文字化け部分が例外としてスローされる状況となっております. 従いまして,状況から察するに,Regex.Unescape以前に問題があるのではないかと考えております.
dodox86

2017/10/08 12:25

コメントありがとうございます。ReadAsStringAsyncではなく、ReadAsByteArrayAsyncでバイト配列を取得し、UWPアプリとコンソールアプリとで違いを調べ、実質的な違いが無ければさらにそれをデコードして正しいUTF16のstringになるかを確認するのも手かと思います。バイト配列に間違いが無ければ、UTF8からUTF16への変換で.NET Coreと.NET Frameworkに差がある、ということになります。(確認だけで、解決策となる訳ではないですが)
退会済みユーザー

退会済みユーザー

2017/10/08 12:29

コメントありがとうございます.まさに今確認中です. 毎回バイト配列が異なるため,確証はありませんが,何回かやってみた所,配列長がコンソールアプリの方が10倍程度のオーダーとなっております. おそらくこのあたりに原因が潜んでいるのではないかと思います・・・
dodox86

2017/10/08 12:33

興味深いですね。UWPアプリ(.NET Core)とコンソールアプリ(.NET Framework)でそもそものHTTPリクエスト自体が異なっていて、HTTPレスポンスの内容も変わってきているのでは、などと思ってしまいました。
退会済みユーザー

退会済みユーザー

2017/10/08 12:37

HTTPについて,最近少しかじり始めたばかりなのでよく分からないのですが,両者の比較をしていたところ,RequestMessage中のVersionプロパティがコンソールでは1.1,UWPでは2.0となっておりました. 調べてみたところ,HTTPのバージョンを指し示しているとのことですが,互換性があるはずで問題は無いと思うのですが,影響しているとことは考えられるのでしょうか・・・・?
dodox86

2017/10/08 12:46

私も決して詳しい訳ではないのですが、影響は考えられます。UWPでHTTP/2.0をHTTPサーバーにリクエストするということは、2.0で新たに追加されたり、許容されるようになった仕様でのHTTPレスポンスをHTTPサーバーがクライアントへ返すことを許すことになります。それで言いますと、HTTPレスポンスの内容が変わる(例:実際、1.1でリクエストしているコンソールアプリの方が10倍程度多い)ことはあり得ると思います。UWPアプリからHTTPリクエストのバージョンを1.1に固定できるようヘッダーを変えることができたら、また挙動が変わるかもしれません。
退会済みユーザー

退会済みユーザー

2017/10/08 16:22

ご丁寧にありがとうございました! 自己解決できましたので,回答を投稿いたしました. 問題の原因ではありませんでしたが,大変ためになるお話しをありがとうございました!
dodox86

2017/10/08 22:30 編集

経過のご報告、どうもありがとうございます。私が提示させてもらった.NET Core由来の問題、とは自分でも少し半信半疑なところもあったので、そうでなくて良かったです。私も勉強になりました。
guest

0

文字コードについては私自身も詳しくないのですが
理解している内容で回答します。(間違っていたらごめんなさい)

UWPアプリのstring型の内部文字コードは、UTF16です。
一方、APTの応答である文字列の文字コードは、UTF8です。
ReadAsStringAsyncでは、応答文字列がUTF8であるにも関わらず
UTF16として取り込んでしまうため、resにセットされた時点で
文字化けすると推察します。

解決策としては、ReadAsStringAsync周辺に文字コードを指定する
プロパティやメソッドなどがあれば簡単かと思いますが
ちょっとだけ調べてみましたが見つかりませんでした。
調べ足りないだけかもしれません。

そこで別の方法がないかググってみたところ、
参考になりそうな記事を見つけたので
貼っておきます。
http://www.atmarkit.co.jp/ait/articles/1501/13/news142.html

ReadAsStreamAsyncとStreamReader(ここで文字コードせっと)とReadToEndAsyncで
文字コードを指定して取得できそうです。

検証していないのではずれかもしれませんが。。。。

投稿2017/10/08 00:28

kikukiku

総合スコア514

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/10/08 10:30 編集

ご回答ありがとうございます. ご提示頂いた改善案は,以下のコードで既に検証しております. var res = await response.Content.ReadAsStreamAsync(); using(var sr = new StreamReader(res, Encoding.UTF8)) { Debug.WriteLine(sr.ReadToEnd()); } しかし,出力に表示されるのは相変わらず文字化けしているという状態です.
退会済みユーザー

退会済みユーザー

2017/10/08 10:44

追記ですが,レスポンスヘッダではContent-Typeの箇所で{application/json; charset=utf-8}となっており,ヘッダ情報に含まれる文字コードデータは問題ないかと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問