java - 尝试为我自己的 XML 样式文件格式编写解析器,但出现 FileNotFoundException,我有什么特别做错的地方吗?

标签 java xml parsing xml-parsing filenotfoundexception

所以基本上,我正在尝试编写一个 2d 骨骼动画编辑器以及一个框架,以便可以轻松地在游戏中使用在编辑器中创建的相同动画。最大的问题是我以前没有写过XML解析器,所以我有一种感觉我可能做错了什么,但我不确定它是什么。

这是我的格式的示例文件:

<skeleton name="skeleton1">

    <bones>
        <bone name="bone1" id="1" textureLoc="/imgs/test.png">
            <position>x,y</position>
            <rotation>float</rotation>
            <scale>float</scale>
        </bone>

        <bone name="bone2" id="2" textureLoc="/imgs/text2.png">
            <position>x,y</position>
            <rotation>float</rotation>
            <scale>float</scale>
        </bone>
    </bones>

    <animation name="anim1">
        <keyframe frameToPlay="1">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>

        <keyframe frameToPlay="50">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>
    </animation>

    <animation name="anim2">
        <keyframe frameToPlay="1">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>

        <keyframe frameToPlay="50">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>
    </animation>
</skeleton>



以下是我组织该系统的方式的描述,如果它使我的代码更容易理解:

AnimationSystem – Management interface for all animations in game, handles updating of each skeleton
--List of skeletons
---Skeletons represent each object
--Update method that updates each skeleton with the game’s current frame
Animation
--List of keyframes
--List of frames, in ascending order, pulled from the list of keyframes
---Order index in list corresponds to order index in list of keyframes
---Should help to speed things up a little bit, no need to search every keyframe to determine which one has a frame value matching the one that is currently needed.
---Will be determined by a set up method after assets are loaded, but before the animation can be used.
--Method to return a keyframe that corresponds to a frame passed to the method
Skeleton
--List of animations
--List of bones
--Value to hold the currently selected animation
--Value to hold the current frame in the game
--Value to hold the name of the skeleton
--Upon moving to a new frame, searches currently selected animation’s list of frames to see if a keyframe should be “played” this frame. If a keyframe exists that should be played at this frame, it should go through each bone in its list of bones, and set the properties of each bone to the properties listed in the keyframe according to the bone’s id.
Bone
--Value to hold the stationary position
--Value to hold the stationary rotation
--Value to hold the stationary scale
--Value to hold the transformed position
--Value to hold the transformed rotation
--Value to hold the transformed scale
--Image value that holds the texture of the bone
--Value to hold the id of the bone within its skeleton
--Value to hold the name of the bone (Used in the editor)
--Method that takes 3 values (position, rotation and scale in that order) and set’s its own transformed pos, rot and scale values to those passed in.
Keyframe
--List of scale values
--List of position values
--List of rotation values
--List of bone ids
---Index of bone id in list matches up to index in scale, position and rotation lists so that the properties can be associated with the bone
--Time value at which the keyframe will be played
--Method to return the scale value of a bone as determined by the bone id passed in
--Method to return the position value of a bone as determined by the bone id passed in
--Method to return the rotation value of a bone as determined by the bone id passed in



我为尝试解析此代码而编写的关联方法如下:

public static Skeleton parseSkeletonFile(String location) throws FileNotFoundException, IOException
    {
        try
        {
            Skeleton skelToReturn = null;

            File fileToLoad = new File(location);

            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(fileToLoad);

            doc.getDocumentElement().normalize();

            NodeList skelList = doc.getElementsByTagName("skeleton");

            for (int counter = 0; counter < skelList.getLength(); counter++)
            {
                Node skelNode = skelList.item(counter);

                Element skelElement = (Element)skelNode;

                skelToReturn = new Skeleton(skelElement.getAttribute("name"));

                NodeList allNodes = skelNode.getChildNodes();

                for (int counter2 = 0; counter2 < allNodes.getLength(); counter2++)
                {
                    Node currentNode = allNodes.item(counter2);

                    if (currentNode.getNodeName() == "bones")
                    {
                        NodeList bonesNL = currentNode.getChildNodes();

                        for (int counter3 = 0; counter3 < bonesNL.getLength(); counter3++)
                        {
                            Node currentBone = bonesNL.item(counter3);
                            Element currentBoneE = (Element)currentBone;

                            Bone bone = new Bone(
                                    currentBoneE.getAttribute("name"),
                                    new Point(
                                        Float.valueOf(currentBoneE.getElementsByTagName("position").item(0).getTextContent().split(",")[0]),
                                        Float.valueOf(currentBoneE.getElementsByTagName("position").item(0).getTextContent().split(",")[1])
                                        ),
                                    Float.valueOf(currentBoneE.getElementsByTagName("rotation").item(0).getTextContent()),
                                    Float.valueOf(currentBoneE.getElementsByTagName("scale").item(0).getTextContent()),
                                    Integer.valueOf(currentBoneE.getAttribute("id"))
                                    );



                            bone.setImage(new Image(currentBoneE.getAttribute("textureLoc")));

                            skelToReturn.bones.add(bone);
                        }
                    }

                    if (currentNode.getNodeName() == "animation")
                    {
                        NodeList animsNL = currentNode.getChildNodes();

                        for (int counter4 = 0; counter4 < animsNL.getLength(); counter4++)
                        {
                            Node currentAnim = animsNL.item(counter4);
                            Element currentAnimE = (Element)currentAnim;

                            Animation animation = new Animation(currentAnimE.getAttribute("name"));

                            NodeList keyframesNL = currentAnim.getChildNodes();

                            for (int counter5 = 0; counter5 < keyframesNL.getLength(); counter5++)
                            {
                                Node currentKeyframe = keyframesNL.item(counter5);
                                Element currentKeyframeE = (Element)currentKeyframe;

                                Keyframe keyframe = new Keyframe(Integer.valueOf(currentKeyframeE.getAttribute("frameToPlay")));

                                NodeList kfBonesNL = currentKeyframe.getChildNodes();

                                for (int counter6 = 0; counter6 < kfBonesNL.getLength(); counter6++)
                                {
                                    Node currentBoneTrans = kfBonesNL.item(counter6);
                                    Element currentBoneTransE = (Element)currentBoneTrans;

                                    keyframe.boneIDs.add(Integer.valueOf(currentBoneTransE.getAttribute("id")));
                                    keyframe.positions.add(new Point(Float.valueOf(currentBoneTransE.getAttribute("transPosition").split(",")[0]), Float.valueOf(currentBoneTransE.getAttribute("transPosition").split(",")[1])));
                                    keyframe.rotations.add(Float.valueOf(currentBoneTransE.getAttribute("transRotation")));
                                    keyframe.scales.add(Float.valueOf(currentBoneTransE.getAttribute("transScale")));
                                }
                                animation.keyframes.add(keyframe);
                                animation.frames.add(keyframe.getTimeToBePlayed());
                            }

                            skelToReturn.animations.add(animation);
                            skelToReturn.animationNames.add(animation.name);
                        }
                    }
                }
            }
            if (skelToReturn != null)
                return skelToReturn;
            else
                return null;
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }



这是我用来测试解析器的代码片段:

AnimationSystem animator = new AnimationSystem();
        try {
            skeleton = animator.parseSkeletonFile(getClass().getResource("SkeletonTest.xml").getPath());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (skeleton != null)
        {
            System.out.println(skeleton.name);
        }


这是在 Slick2D 中构建的一个简单游戏的 init 方法中。我尝试加载的文件 SkeletonTest.xml 与调用解析方法的类位于同一包中。其内容很简单:

<skeleton name="TestSkeleton">

</skeleton>



这是我收到的完整错误消息:

java.io.FileNotFoundException: D:\Eclipse%20Workspace\2dSkeletalAnimator\bin\org\jason\animatorTests\SkeletonTest.xml (The system cannot find the path specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(Unknown Source)
    at java.io.FileInputStream.<init>(Unknown Source)
    at sun.net.www.protocol.file.FileURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.file.FileURLConnection.getInputStream(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
    at org.jason.skeletalanimator.AnimationSystem.parseSkeletonFile(AnimationSystem.java:42)
    at org.jason.animatorTests.AnimatorTest1.init(AnimatorTest1.java:32)
    at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:433)
    at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:357)
    at org.jason.animatorTests.AnimatorTest1.main(AnimatorTest1.java:65)



对于这个有点笼统的问题和所需的背景信息量感到抱歉,但我已经尝试了几乎所有方法来使其正常工作,而无需重写解析方法的主体。我宁愿不再经历那种困惑。所以我希望有更多从 XML 样式文件加载数据经验的人可以帮助我。我感谢提前给我一些时间的人。

最佳答案

一个问题是您试图从类路径条目中获取一个FilegetPath() 方法返回文件 URL,而不是文件路径。然后,您尝试加载它,就好像它是文件路径一样,这会导致问题。

如果您使用getClass().getResourceAsStream(),它会为您提供一个InputStream,这会容易得多。

您可以将 InputStream 传递给您的 parseSkeleton 方法,然后更改为使用 DocumentBuilder#parse(InputStream),而不是传递 location .

使用 InputStream 的另一个优点是,如果您将类打包在 JAR 文件中,您仍然可以加载资源(您将无法获取有效的 JAR 内的文件 路径)。或者您的骨架定义可以来自任何其他InputStream,例如网络等

关于java - 尝试为我自己的 XML 样式文件格式编写解析器,但出现 FileNotFoundException,我有什么特别做错的地方吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14862739/

相关文章:

java - 我如何识别 Java DateUtils.parseDate 中的祖鲁时区?

java - 明确私有(private)方法的编码标准

java - CXF REST 发布 XML 的区分大小写

php - 其他用户无法访问 Magento 2 自定义模块

c# - 可移植类库是否支持 XmlTextReader?

ios - 在 iOS 中是否有将 IP 地址解析为 4 个整数的函数?

python - 如何从文本中删除所有 href 标签

java - 如何为任务计划程序执行控制台 Java 应用程序?

java - 选择将执行哪部分代码,取决于用户的选择

java - JMS 中的多线程