Cảnh báo "ký tự không thể áp dụng để mã hóa" trong Java


112

Tôi hiện đang làm việc trên một dự án Java đang phát ra cảnh báo sau khi tôi biên dịch:

/src/com/myco/apps/AppDBCore.java:439: warning: unmappable character for encoding UTF8
    [javac]         String copyright = "� 2003-2008 My Company. All rights reserved.";

Tôi không chắc SO sẽ hiển thị ký tự trước ngày đó như thế nào, nhưng nó phải là một biểu tượng bản quyền và được hiển thị trong cảnh báo dưới dạng dấu hỏi trong hình thoi.

Cần lưu ý rằng ký tự xuất hiện trong cấu phần đầu ra một cách chính xác, nhưng các cảnh báo gây phiền toái và tệp chứa lớp này một ngày nào đó có thể bị chạm vào bởi một trình soạn thảo văn bản lưu mã hóa không chính xác ...

Làm cách nào tôi có thể đưa ký tự này vào chuỗi "bản quyền" để trình biên dịch hoạt động tốt và ký hiệu được giữ nguyên trong tệp mà không có vấn đề về mã hóa lại tiềm ẩn?


quan tâm đến việc thực sự biết những byte nào tạo nên ký tự bản quyền đó, tức là hexdump AppDBCore.javatôi bằng cách nào đó nghi ngờ nó \u00a9và thay vào đó là thứ gì đó phù hợp với bạn một phần do thiết lập hệ thống của bạn. Dấu chấm hỏi trên được sử dụng để thay thế một nhân vật đến có giá trị là không biết hoặc unrepresentable trong Unicode hexutf8.com/...
jar

Câu trả lời:


56

Sử dụng định dạng thoát "\ uxxxx".

Theo Wikipedia , ký hiệu bản quyền là unicode U + 00A9 nên dòng của bạn nên đọc:

String copyright = "\u00a9 2003-2008 My Company. All rights reserved.";

13
Hãy cẩn thận với các ký tự \ uNNNN ... chúng được phân tích cú pháp trước khi thực hiện phân tích từ vựng. Ví dụ: nếu bạn đặt nhận xét này / * c: \ unit * / vào mã của mình, nó sẽ không biên dịch nữa, vì "nit" không phải là số hex chính xác.
Peter Štibraný

3
Chắc chắn rồi. (Điều này được xử lý tốt hơn trong C #, nơi unicode thoát chỉ áp dụng trong bối cảnh nhất định - nhưng sau đó có nguy hiểm \ x thoát chuỗi là tốt, đó là khủng khiếp.)
Jon Skeet

5
Điều này nghe giống như một chất hỗ trợ ban nhạc hơn là một cách chữa bệnh. Vấn đề thực sự xuất hiện là bạn đang nói với javac mong đợi các tệp nguồn trong UTF-8 khi chúng thực sự ở dạng mã hóa byte đơn như ISO-8859-1 hoặc windows-1252.
Alan Moore

6
@Alan M: Theo kinh nghiệm của tôi, việc đảm bảo rằng bạn sẽ không gặp sự cố khi giữ các tệp nguồn trong ASCII sẽ dễ dàng hơn nhiều so với việc đảm bảo bạn sử dụng mã hóa phù hợp ở mọi nơi mà nguồn của bạn có thể được biên dịch (Ant, Eclipse, Ý TƯỞNG, v.v.).
Jon Skeet

6
@Jon, đó là một lỗ hổng cơ bản trong Java; thực tế là đơn vị nguồn Java được mã hóa theo UTF-8, ISO 8859-1, CP1252, MacRoman, hoặc bất cứ thứ gì, được xử lý ở siêu dữ liệu bên ngoài đơn vị nguồn cần nó. Điều này buộc bạn phải nhớ sửa tệp ant của mình hoặc cấu hình Eclipse, v.v. Như bạn đã chỉ ra đúng, đây hoàn toàn là cách tồi tệ nhất để làm điều đó, vì thông tin rất mỏng manh và dễ bị mất. Các ngôn ngữ giữ siêu dữ liệu (siêu dữ liệu mã hóa) và dữ liệu (đọc: mã nguồn) ở cùng một nơi sẽ mạnh mẽ hơn nhiều ở điểm này. Đó là cách tiếp cận lành mạnh duy nhất.
tchrist

91

Hãy thử với: javac -encoding ISO-8859-1 file_name.java


1
Tôi thích giải pháp này. Tôi đã thêm "-encoding UTF-8" làm trình biên dịch trong ant build.xml của mình và tôi vẫn nhận được "cảnh báo: ký tự không thể áp dụng để mã hóa ASCII". Nếu tôi sửa đổi nó thành "-encoding jjjj", nó sẽ không biên dịch, tôi phàn nàn "error: unsupported encoding: jjjj", vì vậy tôi biết nó đang nhận dạng UTF-8, nhưng có vẻ như nó vẫn được coi là các tệp .java là ascii. Thở dài.
dfrankow

1
Tôi đã thử tham số "mã hóa" của tác vụ ant javac, cùng một vấn đề. Nó nhận ra tham số, nhưng sau đó bỏ qua nó bằng cách nào đó.
dfrankow

20
@dfrankow: bạn phải thêm <compilerarg line="-encoding utf-8"/>theo lệnh <javac>gọi hiện hành trong Build.xmltệp của mình . Đây là một cách làm không tốt, nhưng bạn không có lựa chọn nào khác. Xem bình luận dài của tôi ở trên cùng.
tchrist

Tôi đã gặp vấn đề tương tự khi tôi thêm trình biên dịch trong tập lệnh ant, nó hoạt động tốt, tôi đã xây dựng cái này từ một cửa sổ comandline, điều kỳ lạ là tôi đã xây dựng từ nhật thực, nó đã báo trước bằng cách sử dụng trình biên dịch, trông giống như đó là eclipse thakes care của quyền mã hóa.
simonC

Điều này đã giúp tôi :) cho MAC OSX
Arun Abraham

44

Nếu bạn đang sử dụng Maven, hãy đặt <encoding>cấu hình của plugin trình biên dịch một cách rõ ràng, ví dụ:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>

Đây là cách tiếp cận đúng nếu mọi người đang sử dụng maven để xây dựng dự án của họ, cảm ơn vì đã chia sẻ.
Shamik,

2
Plugin javadoc cũng sẽ phàn nàn về ký tự không thể điều khiển được. Tốt hơn là đặt thuộc project.build.sourceEncodingtính.
Emmanuel Bourg

tôi đã sử dụng thuộc tính project.build.sourceEncoding, nhưng bằng cách nào đó nó không ánh xạ đúng vào thuộc tính mã hóa trình biên dịch. Đặt nó đã làm một cách rõ ràng các trick
Federico Bonelli

32

Điều này đã giúp tôi:

Tất cả những gì bạn cần làm là chỉ định một biến môi trường có tên JAVA_TOOL_OPTIONS. Nếu bạn đặt biến này thành -Dfile.encoding = UTF8, mỗi khi khởi động JVM, nó sẽ nhận thông tin này.

Nguồn: http://whatiscomingtomyhead.wordpress.com/2012/01/02/get-rid-of-unmappable-character-for-encoding-cp1252-once-and-for-all/


wow nó hoạt động. Tôi chỉ cần thêm nó vào .bashrc của tôi và nó đã khắc phục sự cố của tôi.
cowboi-peng,

Hoạt động tuyệt vời, từ dòng lệnh tôi đã nhập để xây dựng: javac MyJavaFile.java -encoding utf-8 -cp .;lib\*Sau đó, khi chạy nó, tôi không cần thêm phần mã hóa bổ sung đó.
Azurespot

23

đặt dòng này trong tệp yor .gradle phía trên conf Java.

apply plugin: 'java'
compileJava {options.encoding = "UTF-8"}   

Bạn có thể muốn thiết lập mã hóa cho compileTestJavavà cho javadoccũng
Frank Neblung

8

Hầu hết thời gian lỗi biên dịch này xảy ra khi biên dịch tệp unicode (được mã hóa UTF-8)

javac -encoding UTF-8 HelloWorld.java

và bạn cũng có thể thêm tùy chọn biên dịch này vào IDE của mình, ví dụ: Intellij idea
(File> settings> Java Compiler), thêm vào làm tham số dòng lệnh bổ sung

nhập mô tả hình ảnh ở đây

-encoding: mã hóa Đặt tên mã hóa tệp nguồn, chẳng hạn như EUC-JP và UTF-8 .. Nếu -encoding không được chỉ định, trình chuyển đổi mặc định của nền tảng sẽ được sử dụng. ( DOC )


8

Các bước Gradle

Nếu bạn đang sử dụng Gradle thì bạn có thể tìm thấy dòng áp dụng plugin java:

apply plugin: 'java'

Sau đó, đặt mã hóa cho tác vụ biên dịch thành UTF-8:

compileJava {options.encoding = "UTF-8"}   

Nếu bạn có các bài kiểm tra đơn vị, thì bạn có thể cũng muốn biên dịch các bài kiểm tra đó với UTF-8:

compileTestJava {options.encoding = "UTF-8"}

Ví dụ Gradle tổng thể

Điều này có nghĩa là mã gradle tổng thể sẽ trông giống như sau:

apply plugin: 'java'
compileJava {options.encoding = "UTF-8"}
compileTestJava {options.encoding = "UTF-8"}

2

Điều này đã làm việc cho tôi -

    <?xml version="1.0" encoding="utf-8" ?>
<project name="test" default="compile">
    <target name="compile">
        <javac srcdir="src" destdir="classes" 
                           encoding="iso-8859-1" debug="true" />
    </target>
</project>

1

Nếu bạn sử dụng eclipse (Eclipse có thể đặt mã utf8 cho bạn ngay cả khi bạn viết ký tự utf8. Bạn sẽ thấy ký tự utf8 bình thường khi bạn lập trình nhưng nền sẽ là mã utf8);

  1. Chọn dự án
  2. Nhấp chuột phải và chọn Thuộc tính
  3. Chọn Tài nguyên trên Bảng điều khiển Tài nguyên (Trên cùng bên phải menu mở ra sau 2.)
  4. Bạn có thể xem trong Bảng tài nguyên , Mã hóa tệp văn bản , chọn cái khác mà bạn muốn

Tái bút: điều này sẽ ổn nếu bạn đặt giá trị tĩnh trong mã. Ví dụ String test = "İİİİİııııııççççç";


1
Mô tả của bạn về “Bạn sẽ thấy [a] ký tự utf8 bình thường khi bạn [đang] lập trình nhưng [nền] sẽ là mã utf8” không có ý nghĩa gì. Ngoài ra, hãy xem bình luận dài của tôi để trả lời câu hỏi ở trên.
tchrist

Tôi đã thay đổi nó thành ISO-8859-1, nhưng vẫn gặp lỗi biên dịch về "ký tự không thể áp dụng để mã hóa UTF8".
pacoverflow

1

Tôi đã gặp sự cố tương tự, trong đó chỉ mục ký tự được báo cáo trong thông báo lỗi java không chính xác. Tôi thu hẹp nó xuống các ký tự dấu ngoặc kép ngay trước vị trí được báo cáo là hex 094 (hủy thay vì trích dẫn, nhưng được biểu thị dưới dạng dấu ngoặc kép) thay vì hex 022. Ngay sau khi tôi đổi sang biến thể hex 022, tất cả đều ổn.


1

Nếu một người đang sử dụng Maven Build từ dấu nhắc lệnh, người ta cũng có thể sử dụng lệnh sau:

                    mvn -Dproject.build.sourceEncoding=UTF-8

1

Đối với những người thắc mắc tại sao điều này xảy ra trên một số hệ thống mà không phải trên những hệ thống khác (với cùng một nguồn, tham số xây dựng, v.v.), hãy kiểm tra LANGbiến môi trường của bạn . Tôi nhận được cảnh báo / lỗi khi LANG=C.UTF-8, nhưng không phải khi nào LANG=en_US.UTF-8.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.